0
votes

I am following along Embers' getting started guide and have a question regarding this step of the "getting started guide": http://emberjs.com/guides/getting-started/marking-a-model-as-complete-incomplete/

In short, we should toggle a boolean property of a model by checking/unchecking a checkbox.

Here is the code in JSBin: http://jsbin.com/UDoPajA/1/edit

I implemented the UI code:

{{input type="checkbox" class="toggle" checked=isCompleted}}

And it seems like everything is working as it should. The UI is updated correctly and Ember inspector tells me the property is being toggled on the model.

The guide also tells me to add a controller as follows:

Todos.TodoController = Ember.ObjectController.extend({
  isCompleted: function(key, value){
    var model = this.get('model');

    if (value === undefined) {
      // property being used as a getter
      return model.get('isCompleted');
    } else {
      // property being used as a setter
      model.set('isCompleted', value);
      model.save();
      return value;
    }
  }.property('model.isCompleted')
});

Is the TodoController as defined in the guide (same step) redundant at this point? If not, what does it add?

3

3 Answers

1
votes

Code in controller is not redundant.

model.save();

this line save model (if you use rest API, this line will generate AJAX request, and your backend will save changes in DB).

1
votes

I think what may be causing you to think that this code may be redundant is thinking that this code is adding a 'Model' at this step. Per your statement: "The guide also tells me to add a model as follows:"

However,

The code that is used to represent your Model is still the same:

 Todos.Todo = DS.Model.extend({
   title: DS.attr('string'),
   isCompleted: DS.attr('boolean')
 });

And your fixture data that uses that Model is still the same:

Todos.Todo.FIXTURES = [
  {
    id: 1,
    title: 'Learn Ember.js',
    isCompleted: true
  },
  {
    id: 2,
    title: '...',
    isCompleted: false
  },
  {
    id: 3,
    title: 'Profit!',
    isCompleted: false
  }
];

What you are doing at this step is adding a Controller, to more specific an ObjectController to control each instance of a todo, then proxy the appropriate data to the Model and the appropriate data at this time is your 'isCompleted' value. But how do you end up with an Object? Lets take a look.

The Todos' template controller is: (Check the spelling 'Todos')

Todos.TodosController = Ember.ArrayController.extend({ ... });

What you now want is control over each individual(object) todo item within that Array (You asked: 'what does this add'). So in order to get back on Object, you implement this code in your handlebars template itemController="todo" which will then wrap each item in its own ObjectController instance named 'todo':

{{#each itemController="todo"}}

Now that you are getting an Object for each todo you implement the ObjectController:

Todos.TodoController = Ember.ObjectController.extend({
  /* same code */
});

Which will then check the 'isCompleted' property for each todo Object then get or set the property's value when the checkbox is toggled.

{{input type="checkbox" checked=isCompleted class="toggle"}}

This code uses a input helper in Ember that renders a 'checkbox' that passes the property 'checked' which is bound to the 'isCompleted property and sets a class 'toggle'

Since it is a boolean value on the model it is going to return either true or false when toggled. The controller is watching for changes to the 'isCompleted' value by setting a computed property:

...}.property('model.isCompleted')

which will then alert the controller and update the template of the change. And also save the Model.

model.save();

Not sure if that clears it up but i hope so. Happy Coding!!

0
votes

Without the customised controller the default controller simply proxies the isCompleted to the model, this will work fine if you do not want the completed state to persist as observed in some of the other answers.

The model.save() persists the change. Of course, when using fixtures this doesn't really achieve very much as refreshing the page will return the state to the original fixtures. If the data was coming from a REST API or similar though, it would actually be updated and that would be reflected upon page refresh.

Also worth mentioning is that because the custom controller declares the function to be a Computed Property, the isCompleted function is treated as a property which is exactly what it was when the default controller was proxying it straight to the model's isCompleted property.

This could really be made a lot more clear in the Ember TodoMVC Tutorial.