Can an entry in an ArrayProxy be bound to a property on some other object?

StackOverflow https://stackoverflow.com/questions/9057294

  •  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.

Était-ce utile?

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>
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top