The Emberist

Ember.js and Related Technologies

Learn More About Ember.js emberjs.com

{{bind}} and {{bindAttr}}

I've noticed recently that there's been some confusion about {{bind}} and {{bindAttr}} in Ember. Both of these helpers serve the same purpose, to bind properties into your templates, so why do we have two versions? To understand this a better, we need to know a bit about how {{bind}} works behind the scenes.

NOTE: {{bind}} is the default helper. If you do {{propName}} it's the same as doing {{bind propName}}. I'll refer to this as {{bind}} throught this post.

{{bind}} at Work

If you look at the source of your page with the WebKit Inspector or Firebug, you'll notice something unusual going on with {{bind}}: it's wrapped in <script> tags! So why do we do this? Well when a bound property updates, we need to know where in the DOM to make the changes. In the SproutCore 2 days, we tried wrapping things in <span> tags. This normally worked fine, except it was a pain to style. People didn't like us messing with their DOM. Furthermore, if you tried to put a binding inside of certain tags like <table> or <select> then things really went downhill.

Metamorph solves these problems by using <script> tags to mark the content so we know where to update. <script> tags are almost entirely transparent to the DOM1. They also are valid nearly everywhere in the document, including inside of <table> and <select> tags. For more information on Metamorph, see its README

But Why Won't It Work?

Imagine the results of using {{bind}} within a tag. If you try the following:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

You'll get something along the lines of:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

This is clearly not valid DOM and it won't work.

This happens because Handlebars isn't context aware. It doesn't know that we are inside of a tag and attempts to output a <script> tag even though it isn't valid.

Enter {{bindAttr}}

{{bindAttr}} works by outputting a data-bindattr attribute in addition to the attribute that you specified. In the previous code, we would change to:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

This instead will output something along the lines of:

404 Not Found

Error: Not Found

The requested URL / was not found on this server.

Ember keeps an internal reference to the binding and, when the property changes, it looks for the tag with data-bindattr-1 and updates the specified attribute.

Now you have a better understanding of not just what you need to do to make things work, but why they actually work.

1. The only known problem in using <script> tags is that they do affect the CSS :first-child, :last-child, and :nth-child selectors. One solution is to use :first-of-type, :last-of-type, and :nth-of-type respectively, though this is not supported in all browsers.


blog comments powered by Disqus