When you have an observable array with non observable elements, and some properties of one of the elements in the array changes, if you want to refresh only that element, you can use indexOf
and splice
, like this:
var changedIdx = obsArray.indexOf(changedItem);
obsArray.splice(changedIdx , 1); // removes the item from the array
obsArray.splice(changedIdx , 0, changedItem); // adds it back
What this does, is looking for the element in the array, removing it, and inserting it back. When it's inserted back, the element is bound again, with the new values.
If you like this solution, you can extend the functionality of all ko observable arrays, like this:
ko.observableArray.fn.refresh = function (item) {
var index = this['indexOf'](item);
if (index >= 0) {
this.splice(index, 1);
this.splice(index, 0, item);
}
}
Then, when you change an item of an array, you simply have to make this call:
obsArray.refresh(changedItem);
If you have many elements in your array you'll get improved performace with respect to the dirty
refresh by Artem Vyshniakov, which updates the bindings for all the elements in the array, and not only for the changed one.
Note: the valueHasMutated
, appart from being undocumented (and for internal use, I suppose), only checks if the array itself has changed, not if the non-observable elements in the array have changed, so it doesn't work. I.e. it only detects if you have added elements to the array, removed elements from the array, changed elements of the array with new, different elements, or changed the order of the elements. But it doesn't check if the elements themselves have changed