The Emberist

Ember.js and Related Technologies

Learn More About Ember.js

Two Way Binding to the DOM

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.

Why {{bind}} Won't Work

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:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

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.

What To Do About It

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.

blog comments powered by Disqus