11

Every google result is about an ArrayController sorting. Need a sorting mechanism without using ArrayController.

There is a model where there are sort params. Like say 'sortOrder' as one of the properties in the model (which will be from a back end).

Will be rendering this model using #each but this should do the iteration based on the sortOrder property and not the model's ID property.

Abhilash L R
  • 805
  • 1
  • 9
  • 24
  • Sorting mechanism: `stuff.sort()`. (Vague question, useless answer. You might want to expand on your use case. What do you want sorted, for starters? How will you use it?) – Amadan May 22 '15 at 02:24
  • http://stackoverflow.com/questions/18855942/how-to-use-ember-sortablemixin – blessanm86 May 22 '15 at 02:36

4 Answers4

31

In Ember 2.0 SortableMixin is deprecated and is on its way out too.

In the Controller (not the ArrayController) you may define a new computed property like SortedUsers1,2,3 below:

export default Ember.Controller.extend({
    sortProps: ['lastName'],
    sortedUsers1: Ember.computed.sort('model', 'sortProps'),
    sortedUsers2: Ember.computed.sort('content', 'sortProps'),
    sortedUsers3: Ember.computed('content', function(){
        return this.get('content').sortBy('lastName');
    })
});

The assumption above is that the model itself is an array of users with lastName as one of user properties. Dependency on 'model' and 'content' look equivalent to me. All three computed properties above produce the same sorted list.

Note that you cannot replace 'sortProps' argument with 'lastName' in sortedUsers1,2 - it won't work.

To change sorting order modify sortProps to

sortProps: ['lastName:desc']

Also if your template is in users/index folder then your controller must be there as well. The controller in users/ would not do, even if the route loading model is in users/.

In the template the usage is as expected:

    <ul>
        {{#each sortedUsers1 as |user|}}
            <li>{{user.lastName}}</li>
        {{/each}}
    </ul>
mp31415
  • 6,531
  • 1
  • 44
  • 34
  • Thank you for this! I saw that ArrayController will be deprecated in 2.0, but nowhere in the docs does it explain how to migrate the sorting. (Except vague mentions of the SortableMixin, which hasn't yet been marked as deprecated in the api docs). And this answer is the only place I could find that explains an alternative. – Dmitri Zagidulin Jul 31 '15 at 19:32
  • 2
    I'm exactly in the same boat, learning this stuff and hitting walls left and right. Ember 2.0 deprecates a lot of stuff, but it's often not clear what to use instead (unless you closely follow Ember development which most of us don't). – mp31415 Aug 01 '15 at 02:19
  • If you're looking to future-proof your code, it's worth remembering that [controllers themselves are on the way out](https://github.com/emberjs/rfcs/pull/15) and this solution too will eventually stop working. – handwovensole Dec 16 '15 at 00:27
  • How to make a refresh #each list after changing sort property on model? – Meliborn Jan 16 '16 at 16:02
  • 2
    I abandoned Ember a while back as I didn't like how complexity grows in the system over time, so cannot help with that. Hopefully somebody from the community may answer. Or maybe it's easier just to make a new question in order to be noticed sooner. Sorry. – mp31415 Jan 16 '16 at 16:10
7

Here is how I manually sort (using ember compare)

import Ember from "ember";
import { attr, Model } from "ember-cli-simple-store/model";

var compare = Ember.compare, get = Ember.get;

var Foo = Model.extend({
    orderedThings: function() {
        var things = this.get("things");
        return things.toArray().sort(function(a, b) {
            return compare(get(a, "something"), get(b, "something"));
        });
    }.property("things.@each.something")
});
Toran Billups
  • 27,111
  • 40
  • 155
  • 268
  • Thank you @toranb. Which do you think is a better way? – Abhilash L R Jun 06 '16 at 04:35
  • 1
    @AryStark just depends on your version of ember/if you are using an ArrayController or if you are in latest ember (not using SortableMixin for example). Both are valid - I was hoping to show the "from scratch" version :) – Toran Billups Jun 07 '16 at 14:50
  • This is better than a computed on a controller, because in theory you can have your data sorted everywhere you access it. Actually could you have an adapter in ember-data that sorts it when received from the api? Would it stay sorted in the store? – Devin Rhode Dec 05 '17 at 01:26
3

You just need to include a SortableMixin to either controller or component and then specify the sortAscending and sortProperties property.

Em.Controller.extend(Em.SortableMixin, {
  sortAscending: true,
  sortProperties: ['val']
});

Here is a working demo.

blessanm86
  • 31,439
  • 14
  • 68
  • 79
0

In situations like that, I use Ember.ArrayProxy with a Ember.SortableMixin directly.

An ArrayProxy wraps any other object that implements Ember.Array and/or Ember.MutableArray, forwarding all requests. This makes it very useful for a number of binding use cases or other cases where being able to swap out the underlying array is useful.

So for example, I may have a controller property as such:

sortedItems: function(){
        var items = Ember.ArrayProxy.extend(Ember.SortableMixin).create({content: this.get('someCollection')});
        items.set('sortProperties', ['propNameToSortOn']);
        return items;
}.property()

Like so: JSBin

mistahenry
  • 8,554
  • 3
  • 27
  • 38