Toggle elements in EmberJS.

Hi there,

In this blogpost I will show you two ways of hiding and showing elements using EmberJS. If you do not know what EmberJS is please here about it here.

So let’s get started. I will be showing you how to do this in an efficient way in other words we won’t be creating a new instance of the show-todos component for every single todos. Instead we will be editing its state on the model.
This is good if you want to display more than 50 todos per page.

npm install ember-cli
ember new todos
cd todos

Add the following to your Router:

//app/router.js
Router.map(function() {
  this.route('todo', { path: '/' });
});

Create a template named todo.hbs.

//app/templates/todo.hbs
<h1>Showing todo list</h1>
{{show-todos action="todoToggler" todos=model.todos}}

So what’s happening above?
We are telling handlebars to look for a component named ‘show-todos’, Components follow a name convention such as name-here if you name your components without a dash you will have to register it manually as ember won’t know how to find it, and we also pass two parameters to it the first one is action and the second is todos. These params can be accessed within the component when it is rendered.

Create a template for the ‘show-todos’ component named show-todos.hbs

{{#each todo in todos}}
  {{#if todo.isNotHidden}}
    <p>{{todo.id}} - <button {{action 'toggleTodo' todo.id}}>Hide</button></p>
  {{else}}
    <p>{{todo.id}} - <button {{action 'toggleTodo' todo.id}}>Show</button></p>
  {{/if}}
{{/if}}

So remember I said the params we have passed in are accessible within the component’s template?
Above we are accessing the todos which points to all the todos that comes from the Controller that we defined.
We are looping through each todo and checking whether they are visible or not. Note that we show a different button name based on its state but we give it the same action name which is defined in the show-todos.js component and we also pass the todo id which will be used later on to find which component we should modify.

Create an Ember component named show-todos.js

//app/components/show-todos.js
import Ember from "ember";

export default Ember.Component.extend({
  actions: {
    toggleTodo: function(id) {
    this.sendAction('action', id);
  }
}
});

Now that’s kinda cool and tricky, Ember ‘sendAction’ knows how to send actions to objects using the ‘action=name…’ that you gave when you called the component from a view.(e.g {{show-todos action=’todoToggler’ ….}}).
It will send an action named todoToggler with an id as the parameter.

Create a todo controller:

//app/controllers/todo.js
import Ember from "ember";

export default Ember.Controller.extend({
  model: function() {
    return {
      [ { id: 1, isNotHidden: true }, { id: 2, isNotHidden: true } ]
    }
  },

  actions: {
    todoToggler: function(todo_id) {
      var todos = this.model.todos,
          todo = todos.findBy('id', todo_id);

      todos.removeObject(todo);
      todo.isNotHidden = todo.isNotHidden ? false : true;
      todos.addObject(todo);
      this.set('model.todos', todos.sortBy('id'));
    }
  }

});

We defined the data that we usually get from calling a model directly into the controller (i.e model property).
Whenever we click on a button defined in app/templates/components/show-todos.hbs it will be calling the action ‘toggleTodo’ that is defined in app/components/show-todos.js that will trigger another action which in this case is ‘todoToggler’ that we defined above in app/controllers/todo.js.
Whenever the todoToggler actions gets called it will fetch all the todos find the todo we want to modify using the todo.id that we passed in as a parameter when we triggered the ‘todoToggler’ from the show-todos component action and it will remove that todo from the todos list, reassign isNotHidden to true if it was false or vice versa, add the newly modified todo and sort by it’s ‘id’ property which will put the todo items in order and set ‘model.todos’ to be it.

So the way Ember works is that none of that will actually change anything on the view until the last bit gets executed and the it will re-render the view for us. If you want to know more about this have a look that the Ember run loop.

So whenever you click on the Show button it will change isNotHidden that is false to true and ember will render the template therefore showing that element.

That’s it for today, I will be posting another way of doing this which is a more expensive way of doing it.

Leave a comment