Computed Properties and Aggregate Data with @each Edit Page
Often, you may have a computed property that relies on all of the items in an array to determine its value. For example, you may want to count all of the todo items in a controller to determine how many of them are completed.
Here's what that computed property might look like:
1 2 3 4 5 6 7 8 9 10 |
App.TodosController = Ember.Controller.extend({
todos: [
Ember.Object.create({ isDone: false })
],
remaining: function() {
var todos = this.get('todos');
return todos.filterBy('isDone', false).get('length');
}.property('todos.@each.isDone')
});
|
Note here that the dependent key (todos.@each.isDone) contains the special
key @each. This instructs Ember.js to update bindings and fire observers for
this computed property when one of the following four events occurs:
- The
isDoneproperty of any of the objects in thetodosarray changes. - An item is added to the
todosarray. - An item is removed from the
todosarray. - The
todosproperty of the controller is changed to a different array.
In the example above, the remaining count is 1:
1 2 3 |
App.todosController = App.TodosController.create(); App.todosController.get('remaining'); // 1 |
If we change the todo's isDone property, the remaining property is updated
automatically:
1 2 3 4 5 6 7 8 9 10 11 12 |
var todos = App.todosController.get('todos'); var todo = todos.objectAt(0); todo.set('isDone', true); App.todosController.get('remaining'); // 0 todo = Ember.Object.create({ isDone: false }); todos.pushObject(todo); App.todosController.get('remaining'); // 1 |
Note that @each only works one level deep. You cannot use nested forms like
todos.@each.owner.name or todos.@each.owner.@each.name.