Sorting in KnockoutJS with ko.plus

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:

  1. Attach a click handler to sort on the specified key when the element is clicked
  2. Inject a caret as a child of the element to indicate what sorting is being applied, if any table