Useful Links
Show All Blog Articles

ToDo MVC with Ember CLI (part 2)

Fri, 25 Jul 2014

Rewrite of the ToDo MVC application from Ember.js guides, following Ember CLI rules.

Part 2 introduces the reader to the notions of model, fixtures and different ways of manipulating model's data.

In part 1 of ToDo MVC with Ember CLI we have built a mockup of the final app, split it in between application and todos templates and showed how to add a custom resource or route to the router.

Modeling Data

Ember Data is a library for robustly managing model data in Ember.js applications. We'll often see ES6 import statements like import DS from 'ember-data'; that signals the usage of Ember Data.

A model is represented by an object that stores persistent state (long term living data).

Let's create the model that describes our todos items (app/models/todo.js).

Note the ES6 style syntax, where everyhting is modularized, instead of using global variables. Thus, we import DS from 'ember-data';, and export in turn export default DS.Model.extend({});. File naming is important, model files are stored in app/models folder and are named as per model name + .js. File names must be lowercase and dasherized if multi-word, so they can be automatically resolved.

As we see in the code snippet above, each todo has two attributes title of type string and isCompleted of type boolean.

Ember Data supports four basic attribute types: string, number, boolean and date. The type can also be ommited, thus title: DS.attr(); expression is valid. If needed, custom types can be added by extending DS.Transform.

To compare your own code with ours, check Modeling Data section code on Github .

Using Fixtures

Fixtures are used to define sample data without the need of querying a backend server.

In Ember Data, the logic for communicating with a backend data store lives in the Adapter. If the set of backend rules is consistent, we can set up an application-wide adapter, called ApplicationAdapter.

In order to instruct our application to use fixtures, we need to define such an adapter that is an extension of the DS.FixtureAdapter. Let's create app/adapters/application.js.

Ember CLI follows again the naming convention. Adapter's folder is app/adapters, whilst the adapter's file name is lowercase, dasherized if multi-word and with a .js extension.

Fixtures are part of the model. To define them, we need to reopenClass for Todo model and the code lives in the same file along with the model: app/models/todo.js.

In the above snippet, we store the model into Todo variable, then we reopen the class reopenClass to add the array of fixtures. The all capital FIXTURES tells that they are constant and the model state is reset to the fixtures value in between succesive runs of the application.

To compare your own code with ours, check Using Fixtures section code on Github .

Displaying Model Data

Let's update the list of todos with dynamic elements, replacing the hard-coded section of todos from our template.

For this we'll need to tell the route to return all todos from our model and pass it further via controller to the view. When we declared our resource in the app/router.js file, a TodosRoute has been created in background. Now we have to override it by creating ourselves app/routes/todos.js.

Let's take a look at the naming convention. The route's name is TodosRoute and its corresponding file is app/routes/todos.js, file name that is lowercase, dasherized when multi-word, .js extenstion. Do you see the pattern?

The model hook in the route returns all records of todo type. Note that when we are passing only one parameter to the find method, this method behaves as a findAll, returning all the records from the named model as a promise.

Next is to loop through all these records in our template app/templates/todos.hbs. Let's replace the static <ul id="todo-list"> ... </ul> list with a dynamic one:

The full listing of app/templates/todos.hbs is on Github .

The router passes the model to the controller, which is an instance of ArrayController in our case. Given the fact that we don't need a custom controller, Ember.js is giving us for free the TodosController, without the need to write any code for it.

The template makes use of each helper to loop over the contents of its controller. {{#each}} ... {{/each}} is a shorthand for {{#each todo in model}} ... {{/each}} loop block. Individual item in the loop is displayed by specifying the attribute: {{title}} in order to display its todo title.

To compare your own code with ours, check Displaying Model Data section code on Github .

Displaying a Model's Complete State

The final Todo MVC application marks completed todos (strike through) by applying completed CSS class to the <li> element. Let's update todos template (app/templates/todos.hbs) to apply the CSS class to this element when isCompleted property is true:

Let's take a look at the line: <li {{bind-attr class="isCompleted:completed"}}>. The expression isCompleted:completed evaluates isCompleted value and if true applies completed class, nothing on false.

If we wanted something like if isCompleted apply completed class, else apply pending class, our line of code could be written as: <li {{bind-attr class="isCompleted:completed:pending"}}>.

Note as well the use of bind-attr, which is used when we want the HTML attributes to be bound to the controller. A more natural way of writting <li class={{isCompleted:completed}}> results in gibberish generated code. It seems that we would be able to write it the easy way when HTMLBars will be released, but until then bind-attr is the way to go.

To compare your own code with ours, check Displaying a Model's Complete State section code on Github .

Playing with Ember Inspector

Our application reads the todo list from our fixtures we defined earlier and displays it when looping in todos template using each helper.

If we would like to debug our application, we can take a quick look at the Ember Inspector and its Data tab. As illustrated in the screenshot below, we can browse the content of thetodo or we can change individual values of the todo model attributes and watch how our application reacts to these changes.

ember inspector data tab


Once again, Ember Inspector proves itself as an essential tool that we should use intensively when developing Ember.js applications.

Useful Links and References

For a better understanding of the content of this article, I strongly recommend reading further the entire Models section from the Ember.js guides.

comments powered by Disqus