Knockout JS: sorting a list based on an element property

Knockout is a JS framework to make building complex apps in the browser a breeze. But somtimes it leaves you with problems that you struggle to figure out.


How exactly do I sort on a property on an object in an observableArray?

say we have an array of these objects
name: "baz",
sales: 10

How would I get sales sorted?

Well it turns out to be reasonable easy, but only once you have thought about it for a while

The key part is sorting on a value. Here is the code

// this will trigger on the selectedSort changes and also...
// when a dpendant observable changes inside the array object. woo!
this.didChange = ko.computed(function() {
for (var i = 0; i < self.arrayForTest().length; i++) {
// here is the magic of ko
tmp = self.arrayForTest()[i][self.selectedSort()]();
return self.arrayForTest.sort(function(a, b) {
return a[self.selectedSort()]() - b[self.selectedSort()]();
}, this);

Knockout has a dependancy observer. It continually looks for changes to observables and bind/unbinds the computed firing based on the contents.
So when we do this:
tmp = self.arrayForTest()[i][self.selectedSort()]();

We are using the ability of js to address a property by name.
arrayItem()[sort field] is the same as arrayItem().sortField

ko can see we are using that observable property in the computed and makes sure it gets re-triggered when that property changes. Sweet.

So now if we loop through all objects and unwrap the property, even by ["sort field"] syntax, ko binds then to the computed.

Change the "sort field" and it unbinds the previous and re-binds.

knockout is a smart cookie. knockout is awesome.