I am having trouble combining the foreach binding with a sort. I have a list bound like so:
<article data-bind="foreach: widgets">
Widgets is a simple obvservable array:
var widgets= ko.observableArray();
This works nicely giving me a list of my "widgets". If I add a new "widget" to this list then it appears dynamically in the list via data binding.
However as soon as I add sorting to the array:
<article data-bind="foreach: widgets.sort(function (left, right) { return left.order() == right.order() ? 0 : (left.order() < right.order() ? -1 : 1); })">
Then newly added widgets no longer appear in my list - unless I reload the page. (The sorting works nicely at this point - if I update the "order" field that I am sorting on then the items in my list are dynamically re-sorted).
How can I go about getting the sorting to play nicely with the dynamic updating of new items in my observable array?
I am using Breezejs in order to retrieve my data, however I do not think that is impacting on this scenario.
Purpose. The foreach binding duplicates a section of markup for each entry in an array, and binds each copy of that markup to the corresponding array item. This is especially useful for rendering lists or tables.
Knockout. js defines an important role when we want to detect and respond to changes on one object, we uses the observable. An observable is useful in various scenarios where we are displaying or editing multiple values and require repeated sections of the UI to appear and disappear as items are inserted and deleted.
The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.
If you want to access the array by index, you need to evaluate the observable first using () . If you want the value binding to work two-ways (i.e.: not only set it initially, but also update the values in your viewmodel after a change), you'll have to bind them to ko.
The observableArray.sort
returns the sorted underlying ("regular") array and not a observableArray
that is why the changes not shown on the UI.
To have the sorting and the UI updated you need to create a ko.computed
which does the sorting and use the computed in your binding. Because the ko.computed
will listen on the widgets
changes and recalculate the sorting.
var widgets= ko.observableArray();
var sortedWidgets = ko.computed(function() {
return widgets().sort(function (left, right) {
return left.order() == right.order() ?
0 :
(left.order() < right.order() ? -1 : 1);
});
});
Then you can bind it with:
<article data-bind="foreach: sortedWidgets" />
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With