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", "[email protected]")
});
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", "[email protected]")
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', '[email protected]')
And it works! Yay!
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', '[email protected]')
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With