I'd like to be able to sort an ArrayController
whose content arises from an ember-data query. Unfortunately, the sortProperty
mixin doesn't seem to work in this case.
I'd like to be able to do the following:
App = Ember.Application.create();
App.store = DS.Store.create({ revision: 4});
App.Item = DS.Model.extend({
id: DS.attr('string'),
name: DS.attr('string')
});
App.store.createRecord(App.Item, {id: '4', name: 'banana' });
App.store.createRecord(App.Item, {id: '2', name: 'apple'});
App.store.createRecord(App.Item, {id: '6', name: 'spaghetti'});
App.ItemsController = Ember.ArrayController.create({
content: App.store.findAll(App.Item),
sortProperties: ['name']
});
With the latest version of Ember
and Ember-data, this gives the output:
[ id: 4, name: banana ]
[ id: 2, name: apple ]
[ id: 6, name: spaghetti ]
The issue here is that App.store.findAll()
returns a RecordArray
whose content property is not simply an array of App.Item
instances (in this case, content is [2, 3, 4])
To actually get my hands on the instances I need to use something like objectAt()
. But even if I extract the App.Item
instances from the RecordArray
and dump them in an ordinary array, things don't work as expected.
Am I missing the obvious way to do this, or is this just the present state of the framework? I'd rather not have to replicate all of my models as plain objects just to sort them.
EDIT:
I got around the issue by making my own custom ArrayController
. Still, it would be nice if things worked as above.
EDIT #2:
Original Handlebars template:
<script type="text/x-handlebars">
{{#each App.ItemsController.content }}
<p>[ id: {{id}}, name: {{name}} ]</p>
{{/each}}
</script>
(Also, I had used a sortProperty
property instead of sortProperties
in my code above, but that was just a typo.)
And yes, if one instead uses
<script type="text/x-handlebars">
{{#each App.ItemsController.arrangedContent }}
<p>[ id: {{id}}, name: {{name}} ]</p>
{{/each}}
</script>
Then we get exactly what we want:
[ id: 2, name: apple ]
[ id: 4, name: banana ]
[ id: 6, name: spaghetti ]
I had the same problem. Took me a while, but eventually this general solution solved it:
App.ArrayController = Ember.ArrayController.extend({
sortProperties: ['id'],
sortAscending: true,
sortedContent: (function() {
var content;
content = this.get("content") || [];
return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
content: content.toArray(),
sortProperties: this.get('sortProperties'),
sortAscending: this.get('sortAscending')
});
}).property("content.@each", 'sortProperties', 'sortAscending'),
doSort: function(sortBy) {
var previousSortBy;
previousSortBy = this.get('sortProperties.0');
if (sortBy === previousSortBy) {
return this.set('sortAscending', !this.get('sortAscending'));
} else {
set('sortAscending', true);
return this.set('sortProperties', [sortBy]);
}
}
});
Now most of my ArrayControllers extend App.ArrayController
instead of Ember.ArrayController
, in particular the ones that have Ember/Data RecordArray
s as content.
Now, in your handlebar templates, do this:
{{#each item in sortedContent}}
...
{{/each}}
instead of
{{#each item in content}}
...
{{/each}}
As of Ember 1.1.2 and ember-data 1.0.0-beta.3, and probably earlier, just setting sortProperties on the Controller is enough. sortAscending
can be set to true
or false
depending on which direction you want to sort.
App.ArrayController = Ember.ArrayController.extend({
sortProperties: ['name'],
sortAscending: true
})
However, note that
sortProperties: ['id']
appears to sort lexically rather than numerically. I got around the lexical sorting by a created_at timestamp, but there may be another way around it.
I had a similar issue and sorted it out via the docs for the array class
in my route I used the sortBy() method. so in your case it might be something like
App.store.findAll().sortBy('name');
I know this is an old question but answering it in case someone, like myself stumbles on by
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With