Basically I have an observableArray and the values for each item are not an observable. This means when I change an item value the UI within a foreach loop of the observableArray does not update accordingly.
It means a massive change if I have to set them to observable, so is there a way I can refresh either the UI or observableArray foreach manually?
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
andsplice
, like this: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:
Then, when you change an item of an array, you simply have to make this call:
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 changedI ended up using the dirty approach from above but made it so that all my observable arrays had this functionality.
The valueHasMutated didn't work for me. Its kind of lame the entire list has to be updated. Or in my case find a way to extend the ko mapping plugin to fill the observable arrays with observable objects..
I'm using Knockout with deferUpdates and the solution of JotaBe needs an update.
It seems Knockout detects, on remove/add, that is the same item and so don't refresh the array.
I have adopted the following solution:
and it refresh the array correctly! :-)
Note I added a second argument to refresh function, for specifying index when index is given, for avoiding indexOf run.
Yes, you can call
valueHasMutated
function for your array:EDIT: If first didn't help you can do 'dirty' refresh:
Here is working fiddle: http://jsfiddle.net/vyshniakov/FuEy6/2/
I found a simple solution by replacing the entire object in the array.
In this example parameter ix is the index, oLine is the updated object and oVM.objProps.lines contains the array. The solution worked like a champ.