Search code examples
ember.jsember-dataember-cli

Sorting data by timestamp on ember


I've looked at a few examples, but haven't been able to reverse-sort, so that newly generated objects are on top.

My sortable items are in components, and I don't think I'm passing sortProperties & sortAscending correctly.

lavender.js:

export default Ember.Controller.extend({
    needs: ['application'],

    sortProperties: ['timestamp'],
    sortAscending: false
});

lavender.hbs

{{#each model.comment as |comment|}}
    {{comment-thread message=comment.message user=comment.user timestamp=comment.timestamp sortProperties=sortProperties sortAscending=sortAscending}}
{{/each}}

comment.js

export default DS.Model.extend({
  message: DS.attr('string'),
  timestamp: DS.attr('date'),

  user: DS.belongsTo('user', {async: true}),
  todo: DS.belongsTo('todo', {async: true}),

});

todo.js (model for lavender.js)

export default DS.Model.extend({
    title: DS.attr('string'),
    isCompleted: DS.attr('boolean', {defaultValue: false}),
    detail: DS.attr('string', {defaultValue: "add details.."}),

    comment: DS.hasMany('comment', {async: true}),
});

There must be something I'm not seeing.. thank you!


Solution

  • You have to use deprecated Ember.ArrayController instead of Ember.Controller if you want your approach to work or you can choose other approach.

    The best approach is to use Ember.computed macro:

    export default Ember.Controller.extend({
        needs: ['application'],
    
        commentsSorting: ['timestamp:desc'],
        comments: Ember.computed.sort('model.comment', 'commentsSorting')
    });
    

    Then, instead of model, iterate over comments in your template.

    You can also use computed property and private(discouraged) Ember.ArrayProxy, like this:

    export default Ember.Controller.extend({
        needs: ['application'],
    
        comments: Ember.computed('model', 'model.comment', function() {
          return Ember.ArrayProxy.createWithMixins(Ember.SortableMixin, {
            sortProperties: ['timestamp'],
            sortAscending: false,
            content: this.get('model.comment')
          });
        })
    });
    

    Then you can iterate over comments in your template:

    {{#each model.comment as |comment|}}
        {{comment-thread message=comment.message user=comment.user timestamp=comment.timestamp}}
    {{/each}}
    

    I don't think you need to pass sort properties to comment-thread, I don't you've misunderstood how this works. It gets sorted in controller, where are all records, not in component, where you have only 1 record per 1 component and no reference to other records.