1

I have a list of object, stored in an arrayController and rendered on the view using the #each macro

{{#each item in controller}}
  {{view App.ItemView}}
{{/each}}

Each item view has class name binding that depends on the user action. For exemple :

App.ItemView = Ember.View.extend {
  classNameBindings: ['isSelected:selected']
}

isSelecteddepends on the state of each Item : I have to store the selected item somewhere, and compare it to the new selected item if a click event is triggered.

The question is: where should I compute this isSelectedproperty ? In the itemsController ? In an itemController? Directly in each itemView ?

2 Answers 2

3

To me, it does make sense to put it into the view as, moreover, it is really a display concern.

You've got an example here: http://jsfiddle.net/MikeAski/r6xcA/

Handlebars:

<script type="text/x-handlebars" data-template-name="items">
    {{#each item in controller}}
        {{view App.ItemView contentBinding="item"}}
    {{/each}}
</script>

<script type="text/x-handlebars" data-template-name="item">
    Item: {{item.label}}
</script>

​JavaScript:

App.ItemsController = Ember.ArrayController.extend({
    selected: null
});

App.ItemsView = Ember.View.extend({
    templateName: 'items'
});

App.ItemView = Ember.View.extend({
    templateName: 'item',
    classNameBindings: ['isSelected:selected'],

    isSelected: function() {
        var item = this.get('content'),
            selected = this.getPath('controller.selected');
        return item === selected;
    }.property('item', 'controller.selected'),

    click: function() {
        var controller = this.get('controller'),
            item = this.get('content');
        controller.set('selected', item);
    }
});

App.ItemsView.create({
    controller: App.ItemsController.create({
        content: [{ label: 'My first item' },
                  { label: 'My second item' },
                  { label: 'My third item' }]
    })
}).append();
​
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for this example. Just one more question: I can't see when the controllerobject is set into the App.ItemView ?
In the sample, it is set at view creation. In 'real life', it would be auto-bound in connectOutlet.
@jrabary I think the controller you mention here is the implicit controller of the children views. If so, in this case, it is inherited from the ItemsView.
I think this solution is fine for the use case described. However, if any additional properties or logic related to the select object comes up, you should refactor to add a separate ObjectController named itemController or selectedItemController and use it's content property to track the selected item.
That's absolutely true. As you can notice: I only intended to provide a short answer limited to the question.
0

It sounds like you need two things - an isSelected property on the item itself (the model) which answers the question, "Is this item selected?", and a selectedItem property on the itemsController, which answers the question, "Which item is selected?" The property on the model is just a get/set; you could compute itemsController.selectedItem by filtering the list of items for one where isSelected is true, or you could set it explicitly with some code to un-select previously unselected items.

3 Comments

This was my first thought but I don't want to clutter my model with additional properties other than those I persist in my database. Hence, I'd like to proxy these properties to an itemController derived from Ember.ObjectController.
I don't mind isSelected attribute on the item is a good idea as it has certainly nothing to deal with the model attributes, being only a display state information.
From the documentation: "We start with controllers rather than exposing the model objects directly to your templates so that you have someplace to put view-related computed properties and don't end up polluting your models with view concerns."

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.