Problem Statement
Sorting inside of Ember.SortableMixin limits us to one order-by clause across multiple properties.
App.AlbumController = Ember.ArrayController.extend({
sortProperties: ['artistname', 'albumyear', 'id'],
sortAscending: true
});
This doesn’t account for numerous use cases:
- Always sort by ID ascending if, for example, album year matches.
- Ability to strictly enforce stability of sorts.
- Creating an advanced sort widget (sort by artist name, ascending, then by release year, descending).
- The entire app that I’m building.
Proposal
Extend Ember.SortableMixin to allow for sorting direction to be applied on a field-level basis.
API Option 1: Extend the existing sortAscending
property to allow passing an array. The push/pop nature of advanced sorting makes this pretty usable. It is also pretty easy to make this backwards compatible and eligible for a point release. Drawback is that it requires two calls to set
in order to accomplish one action.
App.AlbumController = Ember.ArrayController.extend({
sortProperties: ['id'],
sortAscending: [true]
actions: {
sortpush: function(field, ascending) {
var sortProperties = this.get('sortProperties'),
sortAscending = this.get('sortAscending');
// Always sort by 'id' last for stability.
sortProperties.splice(sortProperties.length-1, 0, field);
sortProperties.splice(sortAscending.length-1, 0, ascending);
}
}
});
API Option 2: Create a new sortMultiple
key. This is a more declarative approach, in line with what Ember usually does, but it doesn’t integrate as cleanly into the existing API. Still possible to make backwards compatible, but that is only accomplishable where including sortMultiple
triggers a sort of run-time deprecation of the older sortAscending
approach. I guess it is also possible that sortMultiple
could be treated as syntactic sugar for API Option 1, but that would most easily be accomplished using ES6 stuff I don’t think we can use yet.
App.AlbumController = Ember.ArrayController.extend({
sortMultiple: [
{ property: 'artistname', ascending: false },
{ property: 'id', ascending: true }
],
// sortAscending and sortProperties declarations are ignored, with a bonus debugging assertion.
actions: {
sort: function(property, ascending) {
var sortMultiple = this.get('sortMultiple');
// Always sort by id last for stability.
sortMultiple.splice(sortMultiple.length-1, 0, { property: field, ascending: ascending });
}
}
});
API Option N: This is where you come in. If you don’t like either of my proposed APIs, pitch your own!
I’m also volunteering to write this, so consider this a discussion about whether or not we want to make this change in Ember and what it would look like.
Proof of Need
I am not the only one who has this use case, as demonstrated by this SO post which includes his solution: