Melvin
Melvin

Reputation: 6008

How to bind-attr class active in EmberJS based on an array and a value?

I have a mode array and wants to set the active li based on the active property.

mode: ['list', 'grid', 'table'], // dynamic values
active: 'list',

For output:

<ul>
{{#each mode}}
    <li {{bind-attr class="?:active"}}>
        <a href="#">{{this}}</a>
    </li>
{{/each}}
</ul>

What will I put on the bind-attr part so that if the active property is set on any one of the mode array, it will bind an active class on the li?

Please help.

Upvotes: 0

Views: 361

Answers (1)

merlin
merlin

Reputation: 34

Create a child controller and add a computed property to indicate is active or not:

The ul controller(Use ApplicationController here for simplicity):

App.ApplicationController = Ember.ObjectController.extend({
    mode: ['list', 'grid', 'table'],
    active: 'list'
});

The li controller:

App.LiController = Ember.ObjectController.extend({
    needs: ['application'],

    isActive: function() {
        return this.get('controllers.application.active') === this.get('model');
    }.property()
});

The template:

<ul>
    {{#each mode itemController="li"}}
    <li {{bind-attr class="isActive:active"}}>
        <a href="#">{{model}}</a>
    </li>
    {{/each}}
</ul>

JSBin

Why do i need another controller?

From ember's doc, it says:

In Ember.js, controllers allow you to decorate your models with display logic. In general, your models will have properties that are saved to the server, while controllers will have properties that your app does not need to save to the server.

So, the extra controller's only purpose is to hold the isActive property.

What is {{content}} for?

content represents the controller's underlying object, in this case a string literal. It's not a reserved keyword, it's controller's property.

I updated my answer to use model instead of content, actually they are the same thing, you should always use the model property. See this question

Upvotes: 1

Related Questions