Can an entry in an ArrayProxy be bound to a property on some other object?
-
04-12-2019 - |
Question
I created an example on jsfiddle. I'll also drop the code here:
Javascript:
window.App = Ember.Application.create();
TypeA = Ember.Object.extend({
propertyA: ""
});
TypeB = Ember.Object.extend({
propertyB: ""
});
App.someController = Ember.ArrayProxy.create({
content: []
});
var aa = TypeA.create({propertyA: "aa"});
var ab = TypeA.create({propertyA: "ab"});
var ba = TypeB.create({propertyB: "ba"});
var bb = TypeB.create({propertyB: "bb"});
// I'm probably just copying the string here so sort of realizing
// that the binding "breaks", however I don't get how to maintain the "bond".
App.someController.pushObject(aa.get("propertyA"));
App.someController.pushObject(ab.get("propertyA"));
App.someController.pushObject(ba.get("propertyB"));
App.someController.pushObject(bb.get("propertyB"));
// I'd like this to update the value "aa" in the list
aa.set('propertyA', "AA");
HTML:
<script type="text/x-handlebars">
{{#collection contentBinding="App.someController" tagName="ul"}}
{{content}}
{{/collection}}
</script>
So the source of the entries in someController
can be various different objects, but the bond between the property of the object and the entry in someController should be preserved. Any easy way to do this? I thought of wrapping the values in someController
in some object or view but I can't find how to create a binding to a non "global" object (all the bindings I saw seemed to use a full "global" path, eg "App.someObject.property"
)
Any ideas much appreciated! Thanks.
La solution 2
Okay so I figured it out with help from Veebs post. I wound up wrapping the strings (originating from the property) in an object of the form:
Ember.Object.create({
obj: obj,
out: function() {
return this.get('obj').get(property);
}.property('obj.' + property)
});
Evidently, when a property of an object changes, the object is (somehow) marked changed with it, so by saying that out
depends on obj
it picks up changes in obj.property.
So here is the original code with the changes:
window.App = Ember.Application.create();
TypeA = Ember.Object.extend({
propertyA: "",
propertyC: ""
});
TypeB = Ember.Object.extend({
propertyB: "",
});
App.someController = Ember.ArrayProxy.create({
content: []
});
var a = TypeA.create({propertyA: "aa", propertyC: "ac"});
var b = TypeA.create({propertyB: "bb"});
function createWrapper(obj, property) {
return Ember.Object.create({
obj: obj,
out: function() {
return this.get('obj').get(property);
}.property('obj.' + property)
});
}
App.someController.pushObject(createWrapper(a, "propertyA"));
App.someController.pushObject(createWrapper(a, "propertyC"));
App.someController.pushObject(createWrapper(b, "propertyB"));
setTimeout(function() {
a.set('propertyA', "AA");
a.set('propertyC', "AC");
b.set('propertyB', "BB");
a.set('propertyA', "AA2");
},2000);
...and the (slightly changed) template:
<script type="text/x-handlebars">
{{#collection contentBinding="App.someController" tagName="ul"}}
{{content.out}}
{{/collection}}
</script>
(also available on jsfiddle)
Thanks for the help!
Edit: Second thought, this didn't work, at least not when the update happens after some time. Goddamn it. Edit: Updated to fixed version, yay.
Autres conseils
Hope this is what you are after: jsfiddle.
I think you need to push the objects into the array rather than the property.
App.someController.pushObject(aa);
App.someController.pushObject(ab);
App.someController.pushObject(ba);
App.someController.pushObject(bb);
Then, in your template, reference the required property.
<script type="text/x-handlebars">
{{#collection contentBinding="App.someController" tagName="ul"}}
{{content.propertyA}}
{{content.propertyB}}
{{/collection}}
</script>
By pushing aa.get("propertyA")
into your array, you are just pushing a simple string and the relationship between the object and the array is broken.
I would recommend creating a computed property that will figure out if propertyA
or propertyB
needs to be returned for any one object. Then, you can use the computed property in your collection.
<script type="text/x-handlebars">
{{#collection contentBinding="App.someController" tagName="ul"}}
{{content.newComputedProperty}}
{{/collection}}
</script>