Browsing the blog archives for September, 2014.

I Want to be the One in Control

work safe

It’s all about time. SEP, like most organizations, lives and dies by time sheets. Our time sheets are two weeks long. Each entry has a start time, a project code, a description, and a duration. Easy enough, but what does that have to do with EmberJS?

To Quote Miss Jackson, “I Want to be the One in Control”.

Each timesheet is an array of such entries. If we use an array controller to wrap the array model, we can leverage a lot of assumptions about controlling a number of items.

OK, Computed Properties

Controllers can compute properties, such as the total duration of time logged on a time sheet. In addition, we can validate the timesheet, checking for overlaps and showing the billable time.

App.EntryCollectionController = Ember.ArrayController.extend({
 totalDuration: function(){
   return this.reduce(function(sum,entry){ return entry.duration + sum; },
 0);
 }.property('@each.duration'),
 isValid: function(){
   var otherEntries = this.get('[]');
   this.reduce(function(isValid, entry, index){
     // TODO: the impl of doesntOverlapAfter is left as an exercise to the reader
     return isValid && doesntOverlapAfter(entry, otherEntries, index);
 })
 }.property('@each.startTime', '@each.duration')
});

And we can specify the name of the controller used to wrap each element in the model’s array. In our case, we will use it to calculate the end time from the duration.

App.EntryCollectionController.reopen({
   itemController: 'entry'
});

Objectifying Things for Fun and Profit

Those elements are likely an object controller.

App.EntryController = Ember.ObjectController.extend({
 endTime : function(){
    var time = this.get('startTime').clone();
    time.setMinutes(time.getMinutes() + this.get('duration') * 60);
    return time;
 }.property('startTime', 'duration')
})

All Things are Related

So the collection of entries needs to relate to another controller. In our case, it is the timesheet itself.

App.EntryCollectionController.reopen({
   needs: ['timesheet']
});
1 Comment