How to create Em.computed.sortBy


#1

The built-in computed property types include:

Em.computed.filter   (dependentKey, callback)
Em.computed.filterBy (dependentKey, propertyKey, value)
Em.computed.map      (dependentKey, callback)
Em.computed.mapBy    (dependentKey, propertyKey)
Em.computed.sort     (dependentKey, callback)

I’m curious why there is no computed.sortBy method. Does anyone know of example code doing this?

The provided computed.sort works for elements added/removed from the backing array, but doesn’t reorder elements when their properties change. My first thought is to completely regenerate the sorted array when dependent values change, like this:

mySortedArray: function() {
	return this.get('myArray').sortBy('sortByThis');
}.property('myArray.@each.sortByThis'),

But I think this would invalidate other computed properties that depend on the sorted array, and #each handlers in templates would have to rebuild their contents completely. Is that right?

A computed.sortBy computed property would hopefully update the sorted array piecewise. It may be complicated to implement. (SortableMixin could probably be used.) Any tips appreciated.

PS: ArrayController is great, but this is for general use, e.g. in components or where a template makes use of multiple sorted arrays.


#2

Oh look, right in the API: computed.sort accepts either a function or a property name for the sort definition.

sortMyArrayBy: ['year', 'month', 'date'],
mySortedArray: computed.sort('myArray', 'sortMyArrayBy'),

What the API does not mention is that you can specify descending order like so:

sortByNewestAtTop: ['id:desc'],
mySortedArray: computed.sort('myArray', 'sortByNewestAtTop'),