简体   繁体   中英

Check if an item exists in an observableArray

Why is the check for duplicate Artist always returning false ?

See this JSFiddle for a runnable demo.

Knockout Code

$(function() {

  function Artist(name) {
    this.name = name;
  }

  function ViewModel() {
    var self = this;
    self.favoriteArtists = ko.observableArray([]);
    self.artistToAdd = ko.observableArray("");
    self.addArtist = function () {
      var newFavoriteArtist = new Artist(self.artistToAdd());
      console.log("New Favorite Artist: " + newFavoriteArtist.name);
      var artistExists = self.favoriteArtists.indexOf(newFavoriteArtist) > 0;
      console.log("Artist Exists: " + artistExists);
      if(!artistExists) {
          self.favoriteArtists.push(newFavoriteArtist);
          console.log("A new artist has been added:" + self.artistToAdd());
      } else {
        console.log("Artist already in favorites.");
      }
    };
  }  
  ko.applyBindings(new ViewModel());
});

HTML

<h1>Favorite Artists</h1>
<p>Currently, your favorite artists include:</p>
<ul data-bind="foreach: favoriteArtists">
    <li> <span data-bind="text: name"></span>
    </li>
</ul>
<p>Enter the name of a new artist:</p>
<input data-bind="value: artistToAdd" />
<button data-bind="click: addArtist">Add</button>

Your check should be one of these:

self.favoriteArtists.indexOf(newFavoriteArtist) >= 0

self.favoriteArtists.indexOf(newFavoriteArtist) != -1

self.favoriteArtists.indexOf(newFavoriteArtist) > -1

You're checking whether it's greater than zero. That means that if it's in position 0, artistExists will be set to false because zero is not greater than zero.

That still doesn't work, though. The array is filled with Artist objects, which can't be searched for normally, because the object you search for is different from the object in the array, even if they have the same name value.

Not sure, but self.favoriteArtists.indexOf(newFavoriteArtist) > 0; seems a bit strange, I expect a -1 there. If you add the same artist constantly it will keep thinking it did not exist.

And you keep making new objects, that are not in the list. (complex) objects are not equal to eachother by default.

You can filter the array and check to see if its length is zero. If it is not empty, it contains the item.

return favoriteArtists.filter(function(data) {
      return data === newFavoriteArtist;
    }).length !== 0;

Take a look at this part of code:

var newFavoriteArtist = new Artist(self.artistToAdd());
// ...
var artistExists = self.favoriteArtists.indexOf(newFavoriteArtist) > 0;

Each time you create a new object ( new Artist ). Then you're trying to find new object in a list of old objects ( favoriteArtists ) - and here your code doesn't work as expected.

Instead you could add some another function, which allows you to find artist by name (or some other unique property) and clarify whether this item was added before.

Better is to stop iterating after first element is found instead of go through all collection (so use find, not filter):

return favoriteArtists.find(function(data) {
  return data === newFavoriteArtist;
}) !== null;

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM