Ember.js and Related Technologies
In a previous post, I wrote a bit
about how the {{bind}} and {{bindAttr}} helpers that you can use in
your Handlebars templates. However, if you try to bind to a form input
or other changing element, you'll notice that your changes don't get
recognized. Let me explain to you why this doesn't work and what you can
do about it.
If you read the earlier post,
you'll know that the way {{bind}} and {{bindAttr}} work is by
maintaining a pointer in the DOM so that they can find the right spot to
update when the bound property changes. This works great when you want
to display your properties in the DOM, but it doesn't work so well when
you want DOM changes to modify your properties.
For instance, the following won't work bi-directonally:
<input type="text" {{bindAttr value="valueProperty"}}>
If you think about this a little bit, you might realize why this
approach won't work. Just putting a pointer in the DOM doesn't provide
any notifications when the changes happen from the DOM side. To know
about DOM changes, we need to observe some DOM events. We also need some
custom logic to translate those DOM events into meaningful property
values. After all, a click on a checkbox might change a value from
true to false, but a click on a text field should probably not do
anything.
Fortunately, the cases where we care about DOM changes are fairly
limited. In practice, we only really care about input elements. Ember
comes built in with some controls to help us out in these cases.
Currently, we have TextField, TextArea and Checkbox. These helpers
work by observing the appropriate DOM events and then inspecting the DOM
and setting the view's value (or checked, in the case of Checkbox)
property with the appropriate value.
If you ever want to integrate a custom input widget into Ember, you'll
want to do something along these lines. A custom view subclass provides
for the specialized event handling needed for the specific type of
input. It's a bit more work that it would be if you could just use
{{bind}} or {{bindAttr}}, but as I've explained, these can't do the
trick anyway. This is exactly the sort of job views are good at.