2

In the code below, I render 3 views. The second and third views render App.controller.a. Clicking the first view changes App.controller.a. As you click, the third view updates its content. The second view does not update its content. Why?

I presumed that the second view binds to the array App.controller.a. It looks like the binding is not updating.

Demo: http://jsfiddle.net/kcmH4/

The code:

App = Ember.Application.create({});
App.controller = Ember.Object.create({
    a: Ember.A([1]),
    my_method: function() {
        var a = this.get('a');
        $.each([2], function(i, element) {
            a.pushObject(element);
        });
    }
});
App.MyView = Ember.View.extend({
    click: function() {
        this.get('content').my_method();
    }
});

The template:

{{#view App.MyView contentBinding="App.controller"}}
    First view: Click me
{{/view}}
{{#view Ember.View contentBinding="App.controller"}}
    2nd view: {{content.a}}
{{/view}}
{{#view Ember.View contentBinding="App.controller"}}
    Third view:
    <ul>
    {{#each content.a}}
        <li>{{this}}</li>
    {{/each}}
    </ul>
{{/view}}
hekevintran
  • 22,822
  • 32
  • 111
  • 180

1 Answers1

6

You're binding the second view to an array, but you're not doing it in a helper/view that sets up array observers. As such, the view isn't being informed that the property is changing, because it isn't changing. The array is mutating, but the property itself is not changing. Arrays and objects are passed by reference in JS, so even though you're modifying the contents of the array, unless you're observing changes to the array's contents you won't be notified of any difference. #each uses a collection view which sets up those observers, just binding to the property itself won't.

Christopher Swasey
  • 10,392
  • 1
  • 31
  • 25
  • What helpers can I use to set up array observers? – hekevintran Apr 27 '12 at 20:19
  • 2
    What you should do is instead bind to a computed property that depends on the special '@each' property of an array. Properties that rely on @each will be notified when the array mutates. Then, you can have that property return a string representation of the array to be used stand-alone in your templates. So, you might add: aAsString: function() { return this.get('a').toString(); }.property('a.@each') – Christopher Swasey Apr 27 '12 at 21:15