EmberJS: Unable to get the length of an hasMany array two levels down
Asked Answered
M

2

7

Im trying to create a computed property to get me the sum of the length of all pages.

But i cannot figure out how to access a child so i can get the childs of that child.

App.Document = DS.Model.extend({
    name: DS.attr('string'),
    spreads: DS.hasMany('App.Spread'),

    pagesCount: function() {
                // Here is where i go wrong, i can get the length of spreads, but not access a spread to get the page length.
                var spreadsLength = this.get('spreads.length');
                var firstSpread = this.get('spreads')[0];
                return firstSpread.get('pages.length');
    }.property('spreads')
});

App.Spread = DS.Model.extend({
    document: DS.belongsTo('App.Document'),
    pages: DS.hasMany('App.Page')
})

App.Page = DS.Model.extend({
    spread: DS.belongsTo('App.Spread'),
    page_name: DS.attr('string'),
    page_items: DS.hasMany('DS.PageItem')
})
Myel answered 11/4, 2013 at 14:20 Comment(0)
W
11

Here is an example of how you get access to the first object in the array of spreads:

App.Document = DS.Model.extend({
    name: DS.attr('string'),
    spreads: DS.hasMany('App.Spread'),

    pagesCount: function() {
        // Here is where i go wrong, i can get the length of spreads, but not access a spread to get the page length.
        var spreadsLength = this.get('spreads.length');

        var firstSpread = this.get('spreads').objectAt(0);
        // var firstSpread = this.get('spreads.firstObject'); // elegant way to first Object

        return firstSpread.get('pages.length');
    }.property('spreads.firstObject.pages.length')
});

But i guess you want to get the total number of pages here. So, here is an example how to iterate the spreads and sum the number of pages:

App.Document = DS.Model.extend({
    name: DS.attr('string'),
    spreads: DS.hasMany('App.Spread'),

    pagesCount: function() {
        // Here is where i go wrong, i can get the length of spreads, but not access a spread to get the page length.
        var spreadsLength = this.get('spreads.length');
        var ret = 0;
        this.get("spreads").forEach(function(spread)){
            ret += spread.get('pages.length');
        }
        return ret;
    }.property('[email protected]')
});

Note: Look at the property dependency i declared via property. Since the ComputedProperty depend on those paths, you need to declare them there.

Willable answered 11/4, 2013 at 22:41 Comment(1)
how would you access the length in a template?Daly
L
-3
App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('st    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

});ring'),
  phone: D    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields)    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

}); {
    return fields.firstName && fields.lastNameenter code here
  }

});
    return fields.firstName && fields.lastNameenter code here
  }

});S.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

});

App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

});
  phone: DS.attr('string'),
  status: DS.attr('    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && field    App.User = DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  email: DS.attr('string'),
  phone: DS.attr('string'),
  status: DS.attr('string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

});s.lastNameenter code here
  }

});string', { defaultValue: 'new' }),
  notes: DS.attr('string'),
//  projects: DS.hasMany("project", {async: true}),
    projectsCount: function() {
//    alert(this.get('projects'));
        return this.get('projects.length');
    }.property('id'),

  fullName: function() {
    return this.get('firstName') + ' ' + this.get('lastName')
  }.property('firstName', 'lastName')

}),

App.User.reopenClass({

  valid: function(fields) {
    return fields.firstName && fields.lastNameenter code here
  }

});
Lucylud answered 15/7, 2014 at 9:11 Comment(7)
just pasting code doesn't help. Please consider to add some explanation!Sarsen
@Sarsen - So downvote it. Don't flag it. It is a valid attempt at an answer, so not worthy of deletion.Chardin
@Chardin on the contrary: if it doesn't help, it's just taking up space (not to mention the penalty for downvotes, this isn't worth it)Niedersachsen
@Niedersachsen - The rules are what they are. If you don't like them, bring them up in meta. We should be flagging and deleting things which are not attempts at answers. Things which are attempts at answers, but poor ones at that, should be downvoted if you must do something about them (ignoring them is always an option, too, as is upvoting other, useful answers, or leaving a comment on the answer.) Review Your Answer is in Another Castle - When an Answer is not an Answer: meta.stackexchange.com/questions/225370/…Chardin
@Chardin I agree! And that is what I did! I didn't flag it, just a downvoteSarsen
@Sarsen - My apologies. I was just servicing a flag someone had raised, and given you were the only person to leave a comment on the answer I thought it was you that had raised it. I guess I should have noticed that, given the flag and comment were made 10 weeks apart from each other, that they were probably unrelated.Chardin
@Chardin - no worries :)Sarsen

© 2022 - 2024 — McMap. All rights reserved.