user2024080
user2024080

Reputation: 5101

EmberJS - how to add a class on click?

In my list, when a user click on a fruit that should added a class name as highlight. I am trying for that, But not working. any one help me here? ( when user select other fruit, the previous fruit highlight has to removed ) so only one fruit highlighted on click.

here is my try :

twiddle here

my template :

<h2>This is from Index page</h2>
<ul>
{{#each model as |fruit|}}
    <li {{action "selected" fruit}} class="{{if isSelected 'highlight' ''}}" >{{fruit}}</li>
{{/each}}
</ul>

my route :

import Ember from 'ember';

export default Ember.Route.extend({
  isSelected : false,
  model(){
    return ["Mango","Orange","Apple"]
  },

  actions : {
    selected(fruit){
      console.log( fruit );
        this.toggleProperty('isSelected');
    }
  }
});

Thanks in advance

Upvotes: 1

Views: 376

Answers (1)

nem035
nem035

Reputation: 35491

You're confusing the scope of the Route with the scope of the Controller.

When you're inside a template, the scope is the Controller, not the Route. The template doesn't have access to properties set on the Route.

The reason your action handler still works is because in Ember actions bubble up, first to the Controller, then to the Route, until it finds a an action with the needed name.

The solution is to put your logic inside a Controller:

export default Ember.Controller.extend({
  isSelected : false,

  actions : {
    selected(fruit){
      this.toggleProperty('isSelected');
    }
  }
});

Route

export default Ember.Route.extend({
  model(){
    return ["Mango","Orange","Apple"]
  }
});

The reason the Controller has access to the model property from the Route is because Route has a hook called setupController that by default does this:

setupController(controller, model) {
  controller.set('model', model);
}

Answer for your comment of highlighting one element at a time.

A quick and easy approach would be to, instead of isSelected, you save selectedIndex. Then you can just apply the highlighted class to an item if its index matches the selected index.

Controller

export default Ember.Controller.extend({
  selectedIndex : false,

  actions : {
    selected(idx){
      this.set('selectedIndex', idx);
    }
  }
});

Template:

<h2>This is from Index page</h2>
<ul>
{{#each model as |fruit i|}}
    <li {{action "selected" i}} class="{{if (is-equal i selectedIndex) 'highlight' ''}}" >{{fruit}}</li>
{{/each}}
</ul>

You will also need to create a helper for equality comparison

// helpers/is-equal.js
import Ember from 'ember';

export function isEqual([a, b]) {
  return a === b;
}

export default Ember.Helper.helper(isEqual);

Or use the really good helper library: ember-truth-helpers.

Here's an ember-twiddle example.

Upvotes: 2

Related Questions