A very common UI design pattern is to display an index of items with checkboxes beside them, so that we can select some items and (for example) delete them in bulk.
We may be tempted to implement our template like this:
1 2 3 4 5 |
|
This certainly works. Each item in the collection will get a selected
boolean
property, which we can use to filter the collection of selected items.
But there’s something about this that should make us feel gross: each item in
the collection is likely a model record, which we are polluting with a new
selected
property. Suddenly the model layer cares about what is strictly a
controller-layer concern. The selected
property will persist on the records
even when a user leaves the route and comes back to it later. Not only are we
abusing the separation between controllers and models, but we are potentially
adding nonlocal behaviour to our application.
Luckily, Ember provides a relevant mechanism. If we define an itemController property on an array controller, each item in the collection will be wrapped in an instance of the specified object controller.
Let’s define a CheckboxableItemController
:
1 2 3 |
|
Now we can tell Ember to use it for each item in the array controller:
1 2 3 |
|
Now it’s each instance of CheckboxableItemController
that gets a selected
property, rather than the model it wraps. For good measure, let’s see how we
can define computed properties for retrieving the list/count of selected items,
and an action for removing them.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Note our use of Ember.computed.filterBy
. Critically, we are filtering over
''
(i.e. the controller itself), and not 'content'
. This is because
'content'
is a reference to the underlying collection of items, and not the
wrapped ones.
Have a happy hacking day. □