1
votes

I want to bind parent (arrayController) property with children (itemController). The binding works only when I'm setting the properites in childController like this.set('foo', property), instead using computed properties.

App.IndexController = Ember.ArrayController.extend({
  numberOfAllLetters: (function() {
    return this.getEach('lettersNo').reduce(function(prev, curr){
      return prev + curr
    });
  }).property('@each.lettersNo'),

  numberOfAllLetters2: (function() {
    return this.getEach('length2').reduce(function(prev, curr) {
      return prev + curr;
    })
  }).property('@each.length2')

});

// child
App.WordController = Ember.ObjectController.extend({
  lettersNo: (function() { 
    length = this.get('name').length;
    // why only through 'set' the arrayController binds properly?
    // if in parent controller I bind to '@each.length2', it works good. but why?
    this.set('length2', length); 
    return this.get('name').length;
  }).property('name')
});

handlebars:

<script type="text/x-handlebars" data-template-name="index">

  <ul>
  {{#each word in model itemController="word"}}
    <li>{{input value=word.name}}</li> letters: 
    {{word.lettersNo}}
  {{/each}}
  </ul>
  Total letters:{{numberOfAllLetters}} <br/> <!-- doesnt work -->
  Total letters2:{{numberOfAllLetters2}} <br/> <!-- works -->

</script>

I am wondering if I am missing something and why i cannot use the same property in child's template, child's controller and binded to parent's controller.

Here is the fiddle: http://jsfiddle.net/licancabur/de1k7jcb/

1

1 Answers

1
votes

Both Ember.ObjectController and Ember.ArrayController will be deprecated in future so it's not recommended to use them if you want upgrade your Ember version. So I came up with solution that gets rid of Ember.ObjectController and is working:

App.Word = Ember.Object.extend({
    lettersNo: (function() {
      console.log('lettersNo invoked')
    length = this.get('name').length;
    console.log('length change', length);

    return length
  }).property('name')
});

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return [
        App.Word.create({
            id: 1,
            name: 'one'
        }),
        App.Word.create({
            id: 2,
            name: 'two'
        }),
        App.Word.create({
            id: 3,
            name: 'three'
        }),

    ];
  } 
});

App.IndexController = Ember.ArrayController.extend({
  numberOfAllLetters: (function() {
    return this.getEach('lettersNo').reduce(function(prev, curr){
      return prev + curr
    });
  }).property('@each.lettersNo'),
});

Template:

<script type="text/x-handlebars" data-template-name="index">

    <ul>
        {{#each word in model}}
            <li>{{input value=word.name}}</li> letters: 
            {{word.lettersNo}}
        {{/each}}
    </ul>
    Total letters: {{numberOfAllLetters}} <br/>

</script>

Working JSFiddle.

How I managed to solve it? You were mentioning that you use WordController only in your template - when iterating over words collection(model). Your IndexController didn't know that model has any additional behaviour, so @each.lettersNo simply didn't exist for controller. However, when Ember.Object - App.Word was created - both template and IndexController knew it has computed property lettersNo.