I have just finished working on some new functionality in ko.plus to allow easy sorting of observable collections. The key features are:
- Ability to sort collections on properties and property paths
- Live sorting that reflects changes to observable properties
- Binding handlers to drop in sorting functionality in tables The full documentation is available on GitHub (https://github.com/stevegreatrex/ko.plus) but let’s take a look at some of the features here.
Basic Sorting
The sortable functionality is implemented using an extender so it can be applied to any observableArray in one line:
var myCollection = ko.observableArray([3, 1, 2]).extend({ sortable: true });
// myCollection -> [1, 2, 3]
Without specifying any options the extender will simply sort based on the value using standard JavaScript sort mechanism.
Property Sorting
A more common use case is to sort based on a property of each object in the collection.
var myCollection = ko.observableArray([
{ id: 1, user: { name: ‘Bob’ } },
{ id: 2, user: name: ‘Adam’ } },
{ id: 3, user: { name: ‘Charlie’ } }
]).extend({
sortable: {
key: ‘user.name’
}
});
The key specified can be any valid property name or property path to access the value on which to sort. In the above example, the collection will be sorted by the name of the user property on each object.
Observable Properties
If any of the properties in the specified path are observable then these will be used for the sorting and they will react to any changes to the property.
function ItemModel(name) {
this.name = ko.observable(name);
}
var myCollection =ko.observableArray([
new ItemModel(‘Adam’),
new ItemModel(‘Bob’),
new ItemModel(‘Charlie’)
]);
myCollection()[0].name(‘Dave’);
// myCollection -> [‘Bob’, ‘Charlie’, ‘Dave’]
Binding Handlers
ko.plus includes a new binding handler to assist in sorting a collection on different keys (as would be the case in a table).
<table>
<thead>
<tr>
<th data-bind="" sortby:"="" {="" source:="" mycollection,="" key:="" 'name'="" }"="">Name</th>
<th data-bind="" sortby:"="" {="" source:="" mycollection,="" key:="" 'age'="" }"="">Age</th>
</tr>
</thead>
<tbody data-bind="" foreach:"="" mycollection"="">
</tbody>
</table>
The binding handler has 2 effects: