Ok so, the solution is to link computed properties updated by observable to bubble up the event like this:
App.groupObj = Ember.Object.extend({
group: "style",
name: "Style",
_changed: 0,
changed: function (key, value) {
if (value) {
this.set('_changed', value);
}
return this.get('_changed');
}.property(),
itemChanged: function () {
this.set('changed', +new Date());
console.log('item changed!');
}.observes('[email protected]'),
items: []
});
App.itemObj = Ember.Object.extend({
_val: 6,
id: null,
name: null,
group: null,
fieldType: null,
val: function (key, value) {
if (value) {
this.set('_val', value);
}
return this.get('_val');
}.property(),
computedValue: function () {
return this.val;
}
});
Basically, the grouo object listens to any action on the item's val property and updates his own changed property. this way i can do:
size: function(){
var result = "no size";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'size') result = p.computedValue();
});
}
});
console.log(result);
return result;
}.property('[email protected]')
I guess my first miastake was to think ember was magically going to pickup changes on my nested objects.
I also thought that linking computed properties would work, which obviously didnt! (Why?)
the updated fiddle: http://jsfiddle.net/jmorvan/LEyCD/
EDIT
Since this was pretty long to implement on each object I created my own object with observable based on a selector.
App.changeAwareArray = Ember.ArrayProxy.extend({
init: function () {
this.set('content', []);
this._super();
if (!this.get('changeSelector')) this.set('changeSelector', '_changed');
this.addObserver('content.@each.' + this.get('changeSelector'), this.handleChange);
},
_changed: null,
handleChange: function () {
this.set('_changed', +new Date());
}
});
App.changeAwareObject = Ember.Object.extend({
init: function () {
this._super();
if (!this.get('changeSelector')) this.set('changeSelector', '_changed');
this.addObserver(this.get('changeSelector'), this.handleChange);
},
_changed: null,
changed: function (key, value) {
if (value) {
this.set('_changed', value);
}
return this.get('_changed');
}.property(),
handleChange: function () {
this.set('_changed', +new Date());
}
});
Now you can chain them to observe them:
App.groupObj = App.changeAwareObject.extend({
changeSelector:'items._changed',
group: "style",
name: "Style",
items: App.changeAwareArray.create()
});
App.itemObj = Ember.Object.extend({
_val: 6,
_changed: null,
id: null,
name: null,
group: null,
fieldType: null,
val: function (key, value) {
if (value) {
this.set('_val', value);
this.set('_changed', +new Date());
}
return this.get('_val');
}.property(),
computedValue: function () {
return this.val;
}
});
And get the data in your view/controller:
App.IndexView = Ember.View.extend({
init: function () {
this._super();
//populate the Array
this.data.properties.pushObject(createData());
},
elementId: "test",
size: function () {
var result = "no size";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'size') result = p.computedValue();
});
}
});
return result;
}.property('data.properties._changed'),
offset: function () {
var result = "no offset";
this.get('data.properties').forEach(function (g) {
if (g.group == "style") {
g.items.forEach(function (p) {
if (p.id == 'offset') result = p.computedValue();
});
}
});
return result;
}.property('data.properties._changed'),
data:{
name: "base",
properties: App.changeAwareArray.create()
}
});
you can find a working fiddle here: http://jsfiddle.net/jmorvan/VRVac/