简体   繁体   中英

How to merge (aggregate) nested model collections in EmberJS?

Consider this model:

Grandparent
  parents: DS.hasMany('parent')

Parent:
  grandparent: DS.belongsTo('grandparent')
  children: DS.hasMany('child')

Child:
  parent: DS.belongsTo('parent')

I want to add a computed property children to Grandparent model, in which I expect a collection of Child models (Grandparent.children = merge each Grandparent.parents.children).

How to do that?

For this example data:

Grandparent { id: 0, parents: [0, 1] }

Parent { id: 0, grandparent: 0, children: [0] }
Parent { id: 1, grandparent: 0, children: [1,2] }

Child { id: 0, parent: 0 }
Child { id: 1, parent: 1 }
Child { id: 2, parent: 1 }

I want Grandparent.get('children') to return children with ids [0, 1, 2].

EDIT:

App.Grandparent.reopen({
  grandchildren: function(){
    var result = [];
    this.get('parents').forEach(function(parent) {
      parent.get('children').forEach(function(child){
        console.log('is this even called?');
        result.push(child);
      });
      console.log('coz this is!');
    });
    return result;
  }.property("parents", "parents.@each.children")
});

Why is the second loop empty? I know data is loaded (ember inspector).. so why is it not accesible here?

EDIT2:

Almost there! It seems the list was empty, becouse it was a promise array (which was not yet resolved), therefore at the time the code was executed - it was empty!

 grandchildren: function(){
    var grandchildren = [];
    this.get('parents').forEach(function(parent) {
      var promiseArray = parent.get('children');
      promiseArray.then(function() {
        promiseArray.forEach(function(child){
          grandchildren.push(child);
          console.log(child);
        });
      });
    });
    return grandchildren;
  }.property("parents", "parents.@each.children")

So this code correctly displays in console log all the grandchildren... but! it still does not return them. It's probably for the same reason - at the time the code hits return grandparent it's still empty. I'm thinking now, is there a way around that?

EDIT3:

It seems the root of the problem is the DS.hasMany('parent', { async: true }) and DS.hasMany('child', { async: true }) . I've ommited the async part in the original question to make the model example more clear.

EDIT4:

I have solved my problems by removeing the async: true from the DS.hasMany and used this script to load them correctly without async.

This fixed the problem with "empty arrays" (unresolved promise arrays) and allowed me to access the properties. Then I did the following code (in the MODEL's reopen function):

grandchildren: function(){
  var res = Ember.ArrayProxy.create({content: Ember.A()});

  this.get('parents').forEach(function(parent){
    res.pushObjects(parent.get('children').toArray());
  });

  return res;
}.property('parents', 'parents.@each.children')

And it works! Yay!

However, I'm still interested in the solution for ASYNC data

The next step is replaceing the fixtures with some data fetched from the server. And that data is asynchronous.. so I still need a solution with promises.

EDIT5: Test code:

grandchildren: function(){
  var res = Ember.ArrayProxy.create({content: Ember.A()});

  this.get('parents').forEach(function(parent) {
      var promiseArray = parent.get('children');
      promiseArray.then(function() {
        res.pushObjects(promiseArray.toArray());
      });
    });

  return res;
}.property('parents', 'parents.@each.children')

You may be looking for http://emberjs.com/api/classes/RSVP.html#method_all .

var promises = [];
this.get('parents').forEach(function(parent) {
  promises.push(parent.get('children'));
});
return Ember.RSVP.all(promises).then(function(results) {
  // return concatenated results
});

When you call grandchildren you will get a promise that resolves to the concatenated results.

In the future it looks like there will be support for hasMany through similar to rails. https://github.com/emberjs/data/issues/120

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM