Billybonks
Billybonks

Reputation: 1568

Retriving models for HasMany relationship

I have two models

Time Entry

TimeTray.TimeEntry = DS.Model.extend({
    startTime: DS.attr('date'),
    endTime: DS.attr('date'),
    status: DS.attr('string'),
    offset: DS.attr('number'),
    isDeleted: DS.attr('boolean'),
    task: DS.belongsTo('task'),
    duration: function () {
        return TimeTray.timeController.duration(this.get('startTime'), this.get('endTime'));
    }.property('startTime', 'endTime'),
    title: function () {
        if (this.get('task')) {
            return this.get('task').get('title');
        }
    }.property('task')
});

Task

TimeTray.Task = DS.Model.extend({
    title: DS.attr('string'),
    totalTime: function () {
        var timeEntries = this.get('timeEntries')
        for (var entry in timeEntries) {
           var duration =  entry.get('duration')
        }
    }.property('timeEntries'),
    isDeleted: DS.attr('boolean'),
    isRecording: DS.attr('boolean', { defaultValue: false }),
    timeEntries: DS.hasMany('TimeEntry')
});

how do i get an array of timeentry entities so that i can calculate the total time spent on a task? the above method doesnt work.

the Time Entry title property works.

Upvotes: 0

Views: 89

Answers (2)

Marcio Junior
Marcio Junior

Reputation: 19128

You have some errors in your code:

1- In that foreach

...
for (var entry in timeEntries) {
  var duration =  entry.get('duration')
}
...

The for ... in not work like you expected for arrays, you need to use or for(var i; i < array.length; i++) or the array.forEach(func).

2 - In the computed property totalTime you will use the duration property of the TimeEntry, you need to specify that dependency using property('[email protected]').

3 - Probally your timeEntries property will be fetched from the server, so you will need to use the async: true option, in your definition:

timeEntries: DS.hasMany('TimeEntry', { async: true })

4 - If your timeEntries is always empty, even the data being saved in your database. Make sure that your returned json have the timeEntries ids. For example:

{id: 1, title: 'Task 1', timeEntries: [1,2,3] }    

The changed code is the following:

TimeTray.Task = DS.Model.extend({
    title: DS.attr('string'),
    totalTime: function () {
        var duration = 0;
        this.get('timeEntries').forEach(function(entry) {
            duration += entry.get('duration')
        });
        return duration;
    }.property('[email protected]'),
    isDeleted: DS.attr('boolean'),
    isRecording: DS.attr('boolean', { defaultValue: false }),
    timeEntries: DS.hasMany('TimeEntry', { async: true })
});

And this is the fiddle with this sample working http://jsfiddle.net/marciojunior/9DucM/

I hope it helps

Upvotes: 1

chopper
chopper

Reputation: 6709

Your totalTime method is neither summing timeEntry durations nor returning a value. Also your property is not set up correctly (use @each). The correct way of doing this is:

totalTime: function () {
    var timeEntries = this.get('timeEntries')
    var duration = 0;
    for (var entry in timeEntries) {
       duration = duration + entry.get('duration');
    }
    return duration;
}.property('[email protected]'),

Or, more elegantly using getEach() and reduce():

totalTime: function () {
    return this.get('timeEntries').getEach('duration').reduce(function(accum, item) {
        return accum + item;
    }, 0);
}.property('[email protected]'),

Upvotes: 0

Related Questions