javascriptdateember.jscoffeescriptmomentics

Filter Model In By Dates in Ember Controller


I am having this DS.Model

   Model = DS.Model.extend

  date: DS.attr "string"
  amount_payed: DS.attr "string"
  user_name:DS.attr "string"

`export default Model`

Currently there is nothing in my controller

Controller = Em.Controller.extend()

export default Controller

This is the route

 Route = Ember.Route.extend 

  model: () ->
    return @store.find "user-account"

`export default Route`

From server I m getting response in json with date value like

"date": "1995-12-25 00:00:00"

This is the sample template

{{#each detail in model}}
 <li>{{detail.date}}{{detail.amount_paid}}{{detail.user_name}}</li>
{{/each}}

How to I sort/filter the model in my controller so that when the template renders the model using {{#each detail in model}} the details with latest dates are displayed first.Basically I want to sort the model using date property.Remember date comes like "date": "1995-12-25 00:00:00". Will be ok if u guys can give a solution in javascript also(not necessarily coffescript)


Solution

  • There's several ways you could do this: computed.sort, SortableMixin, implementing a custom sorting function.

    The tricky thing currently is that your dates are strings, so you will need to convert them to something you can run comparisons on (either numerical timestamps, or date objects, etc.). You could either do that conversion during the sort (within the sorting function), or on the model itself so that you can reuse and format the date more easily in other places in your app.

    The example I'm providing below does the conversion during the sort. Note, you can't just do (new Date(string)) because of a bug with date parsing in Safari.

    This answer assumes use of ember-cli and syntax that is current best practice as of Ember 2.0

    Docs for computed.sort are here: http://emberjs.com/api/classes/Ember.computed.html#method_sort

    import Ember from 'ember';
    
    const {
      computed,
      Controller
    } = Ember;
    
    export default Controller.extend({
      sortedModel: computed.sort('model', function(a, b) {
        let timestampA = makeTimestamp(a);
        let timestampB = makeTimestamp(b);
    
        if (timestampA > timestampB) {
          return 1;
        } else if (timestampA < timestampB) {
          return -1;
        }
        return 0;
      })
    });
    
    
    // ideally you'd just return date, and call this makeDate
    // and probably you'd do this when setting the date onto the model
    function makeTimestamp(dateString) {
      let arr = dateString.split(/[- :]/);
      let date = new Date(arr[0], arr[1]-1, arr[2], arr[3], arr[4], arr[5]);
      date.setTime( date.getTime() - date.getTimezoneOffset() * 60 * 1000 );
      return date.getTime();
    }
    

    You would then use this in your template like this.

    {{#each sortedModel as |detail|}}
      <li>{{detail.date}}{{detail.amount_paid}}{{detail.user_name}}</li>
    {{/each}}
    

    Quick note, {{#each detail in model}} is a deprecated syntax, the current syntax as of ~1.10 is {{#each model as |detail|}}.