3
votes

I am trying to use Emberjs sortProperties to sort content by date in this jsfiddle. My model has a startTime property which I tried to sort by but it didn't work. I then created a computed property called todayEvent in the controller which returns events that match the passed in date and I tried to sort that but it also didn't work. All I am trying to do is list events occurring on same day but in such a way that time of the day in chich event occurs is sorted in ascending order for example, an event occurring by 10am should be listed before those occurring by say 12pm.

This is the jsfiddle

The model:

App.TimeSlot = DS.Model.extend( {
  startTime: DS.attr('date'),
  endTime: DS.attr('date'),
  allDay: DS.attr('boolean'),
  soldOut: DS.attr('boolean')
});

The controller

App.TimeSlotController = Ember.ArrayController.extend({
 content: [ ],

 sortProperties: ['todayEvent'],
 sortAscending: true,

 day: Ember.A(['2013-10-25']),

 todayEvent: function(){
  self = this;
  u = self.get('content'); 
  console.log('u', u);
  kl =  u.filter(function(availableSlot) {
   console.log ('a', availableSlot.get('startTime') );

 return (moment(availableSlot.get('startTime')).format("YYYY-MM-DD") ==  self.get('day').toString() );
  }); 

   return kl;  
 }.property('day', 'content@each'),


});

The fixtureAdapter

App.TimeSlot.FIXTURES = [

  {
    id: 3,
    startTime: moment.utc('2013-10-25T12:30:00+01:00',"YYYY-MM-DD HH:mm:ss" ),    
    allDay: true
  },

 {
   id: 4,
   startTime: moment.utc('2013-10-25T10:10:00+01:00',"YYYY-MM-DD HH:mm:ss" ),    
   allDay: true
},

 {
  id: 5,    
  startTime: moment.utc('2013-10-23 00:00 +01:00', "YYYY-MM-DD HH:mm"),    
  allDay: true
 }
];
5

5 Answers

5
votes

I managed to solve it @edu but thanks for trying to help. You can see a working jsfiddle.

There are two approaches and both use Ember.computed.sort:

 sortedTime: Ember.computed.sort('todayEvent',       function(a, b){

    if (
      moment(Ember.get(a, 'startTime') ) >  moment(Ember.get(b, 'startTime') ) 
    ){

   //returns morning timings before afternoon timings
   //api doc says return 1 when 'a' should come after 'b'
   //http://emberjs.com/api/#method_computed_sort

   return 1;

   } else if ( 
      moment(Ember.get(a, 'startTime') ) <   moment(Ember.get(b, 'startTime') ) 
   )
   {
    //returns afternoon timings before morning timings
   //api docs says return -1, when 'a' should come before 'b'
    return -1;
   }
     return 0;

  })

The second approach

  //adapted from http://jsbin.com/OjoXOqE/9/edit

  sortedContent: Ember.computed.sort('[email protected]', function(a, b){

    //the this keyword does not work here, 
    //throws "Object #<Object> has no method 'get'"
    //so we use the Ember keyword to get it working

   var ap = moment(Ember.get(a, 'startTime')),
       bp = moment(Ember.get(b, 'startTime'))

  //we return morning before afternoon times 
    if(ap !== bp) {
      return ap - bp;
    }

  })
3
votes

Use .sortBy() to sort an array of objects containing dates.

In your model:

fooDate: DS.attr('date')

In your component/controller/route:

dateSortedFoos: function() {
  return this.get('model.foos').sortBy('fooDate');
}.property('model.foos.@each'),

No need to iterate through or to use Moment JS.

Works with dates in this format "2015-09-11T08:15:00+10:00".

For reference: I'm using Ember 1.13.10 and Ember Data 1.13.9.

2
votes

You can simply override sortFunction on your ArrayController. See Sort Function

App.TimeSlotController = Ember.ArrayController.extend({
  sortProperties: ['startTime'],
  sortAscending: true,
  sortFunction: function (dateX, dateY) {
    return Ember.compare(dateX.getTime(), dateY.getTime());
  }
1
votes

The sorted content of the controller lives in the property named arrangedContent, so inside controller you should call

this.get('arrangedContent')

or in handlebars

{{#each arrangedContent}}

Hope this help

1
votes

I know this is an old question, but I figured out that I will post a new, more 'up-to-date' answer.

To sort an iterable by dates, you can use Ember.computed.sort in this way:

export default Ember.Component.extend({
//...stuff
eventsArray: [
  {eventName: 'Event One', date: dateObject1},
  {eventName: 'Event One', date: dateObject2},
],
eventsArraySortDefinition: ['date:ascending],
sortedStuff: Ember.computed.sort('eventsArray', 'eventsArraySortDefinition'),
//...stuff
})

It is worth noting, that when you define a model property with type 'date' ( date: DS.attr('date') ) than a date in a string format like '2016-10-17' will be nicely converted and stored in the model as a Date object. During sorting, the date will be explicitly converted to a timestamp, so you don't need to do any convertion yourself.