How to conditionally push an item in an observable array?

Solution 1:

An observableArray exposes an indexOf function (wrapper to ko.utils.arrayIndexOf). This allows you to do:

if (myObservableArray.indexOf(itemToAdd) < 0) {
  myObservableArray.push(itemToAdd);
}

If the two are not actually a reference to the same object and you want to run custom comparison logic, then you can use ko.utils.arrayFirst like:

var match = ko.utils.arrayFirst(myObservableArray(), function(item) {
    return itemToAdd.id === item.id;
});

if (!match) {
  myObservableArray.push(itemToAdd);
}

Solution 2:

Thanks RP. Here's an example of using your suggestion to return the 'name' property via the object's 'id' property from within my view model.

    self.jobroles = ko.observableArray([]);

    self.jobroleName = function (id)
    {
        var match = ko.utils.arrayFirst(self.jobroles(), function (item)
        {
            return item.id() === id();  //note the ()
        });
        if (!match)
            return 'error';
        else
            return match.name;
    };

In HTML, i have the following ($parent is due to this being inside a table row loop):

<select data-bind="visible: editing, hasfocus: editing, options: $parent.jobroles, optionsText: 'name', optionsValue: 'id', value: jobroleId, optionsCaption: '-- Select --'">
                            </select>
<span data-bind="visible: !editing(), text: $parent.jobroleName(jobroleId), click: edit"></span></td>