Some notes on Javascript Templates, databinding, and related stuff

As a follow-up to my previous post about how HTML files could be treated as application views, I'd like to take some time to dive deeper into a notion which has seemingly become essential in JS based application development: templating. And before you ask: yes, deep inside, I'm convinced this picture is absolutely relevant to this whole story.
But first, please keep in mind that topic is still relatively new to me (at least when compared to my background with the flash platform) so the following is definitely subject to some caution and should be considered as "early conclusions". So I guess what I mean is that I'd really love to have your input on all this. ;)
A small introduction to JS templates
Javascript templates are essentially a way to address the need to populate an HTML view with data in a better way than having to write a big, ugly string concatenation expression.
Many JS frameworks have a notion of templates, like the one you find in underscore.js, or the jQuery tmpl plugin. You also have dedicated solutions like Mustache or Handlebars. The idea is pretty much the same in all cases, only the implementation and APIs change.
So most of the time you'll have to write a string which describes some HTML markup "augmented" with a special syntax, and then pass it to a method which will replace the special syntax with the actual object values and return the resulting DOM.
The first step is to write the template string. A popular syntax for this is the Mustache syntax, used by much more templating engines than Mustache.js, which uses double brackets to include expressions.
var templateString= "<h1>{{title}}</h1>";
The template then needs to be processed before being used. This process is often called "compiling".
Using underscore.js…
var compiledTemplate = _.template(mytemplate);
Using Handlebars.js…
var compiledTemplate = Handlebars.compile(mytemplate);
The logic in place here is actually pretty simple: it's all about splitting the template string using regexps and concatenate it with the object values inside a function. If needed, you could easily create your own utility to replicate this "templating behavior", as shown here or there for instance.
The returned function which can then be used to actually take an object and have it match the template in order to get the resulting DOM. This process is sometimes called "rendering".
var someObject = {title:"Hello World"};
var resultingHTMLString = compiledTemplate(someObject);
Note: what I'm not showing here is that most template syntaxes let you include complete javascript expressions to do pretty much whatever you want. There are many resources about various implementations on the web. As an example, my colleague Christophe Coenraets has a nice post about Mustache.js.
In some cases, compiling and rendering can be done in one function call, as with Mustache.js toHTML(), or jQuery-tmpl plugin tmpl() methods. But it's important to understand that in any case those two steps (compiling and rendering) are involved.
Best practices
Compiling the template string to a JS function can be really slow. For this reason you may want to cache or even "pre compile" a template.
If you compile your templates at runtime, client side, you really want to keep a copy of the template function in a sort of cache. Here's a caching example for underscore.js stolen inspired from alex sexton jquery's best friends presentation.
var templatecache = {};
function render(name, obj) {
if (! templatecache[name]) {
templatecache[name] = _.template(
$('#tmpl-'+name).html()
);
}
return templatecache[name](obj);
}
Note that many templating engines include their own caching mechanism, internally.
Alternatively, you could also pre-compile templates, to get rid of the client side compiling altogether, and even minify the resulting js. You can then integrate the result back to your development process. But this raises another issue: how are we supposed to integrate those templates in the first place?
Let's not forget that before being compiled, templates are just strings. Even if template strings can be placed anywhere, most implementations suggest to include it in a <script> tag or any other hidden element.
Consider this ultra simplistic template described inside a script tag (note the use of the id attribute to reference the template).
<script id="template1" type="text/html">
<h1><%= data.title =></h1>
</script>
We can then access it later like this:
var t = $('#template1').html();
… and pass it to our compiling method, as mentioned before.
Now, coming from a flex background or not, declaring templates as strings is frustrating, if only because strings are not interpreted as DOM by HTML editors. Also, declaring them inside you main application view is completely anti-DRY.
So how can we address that?
First of all, even if the template needs to be a string at some point, you can just declare it inside the regular page DOM, and keep the ability to edit the source in an HTML editor. Angular.js, which is much more than a templating engine, has an elegant way to allow just that. However, I guess this could raise some concerns regarding semantics (but that's clearly not something I know a lot about).
Another example would be Pure.js but here there is no special syntax inside the view referencing data, js objects called directives do the actual job of matching the markup with the object values.
However I think the most common pattern you find out there is to simply declare templates as external files. Once you have done that, you can either:
- use a build utility which automates the integration of templates inside script tags ( A good pre compiler tool for mustache templates would be mojo )
- use a server side logic to assemble the single page from the various template files
- load them dynamically, which is probably the most common case.
A good idea would be to use Require.js, the popular script loader, since templates files can be treated as dependencies. It would also have the advantage of permitting to do it server side via node.js.
What about data binding?
In my opinion, one of the most powerful tools flex gave us is data binding. It's an expressive and very productive way to describe the relationship between a view and the data it exposes. Unfortunately, web standards do not expose such an elegant declarative mechanism, so we have to rely on ourselves -and frameworks- do to the job.
By now, you probably have noticed that templates are actually just a functions which take an object as a parameter and concatenate a string with objects properties. And of course, concatenation is done once, at the time you the call the template method.
In other words, there is absolutely no actual "binding" happening here. If the object values change, your view is not updated, so you still need to call the template function by yourself.
Sometimes, this behavior is good enough. Many dynamically created views do need to be updated. They are created (and destroyed) at runtime just to represent the state of an object at a particular moment. In my experience, that's typically the case with so called "item renderers", i.e. views representing a item in a data list.
Theoretically, you can use this as a basis for data-binding. All you need to do is observe changes at the object level, and call the template in case of a change. However, that's easier said than done, and repainting a whole view for the change of only one value is not really optimized.
Note: Conversely, with flex and MXML, we only have one syntax to match an object data to the view and to automate the binding. This is also kind of unoptimized for the many cases where you don't expect any change at the object level.
Some more sophisticated frameworks offer features that are much closer to what you have in flex, like knockout.js 's declarative binding. In that case, you have a real observer pattern taking place, looking at your object values, and updating the related UI in case of a change.
It uses the new data- attribute to specify what binding should take place: using the following syntax on the view
<tag data-bind="destination:source"></tag>
Where destination is the property of the view that should be written and source is the property of the data object used as a source.
Here's a very simple example:
<p>Name:<span data-bind="text: name"></span></p>
<script>
var viewModel={name:"David"};
ko.applyBindings{viewModel}
</script>
The applyBindings method is one who does the trick here, which means is if you want to update your views when your model has changed, you still have to call this method.
If you want to go further, here's a nice post about knockout.
Angular also implements databinding by default. And I think Backbone has some plugins to do pretty much the same, but I admit I didn't have time to really dive into it.
Another specific implementation I've found is the jQuery Data-linking plugin (done by Microsoft, like the tmpl plugin). A nice article about this plugin can be found at Microsoft msdn.
I'm sure there are more implementations of databinding in other frameworks, but I simply didn't take the time to research them, so feel free to add other tips and recommendations in the comments !

switcherdav (not verified) on December 27th 2011
Hi David, did you plan to propose an RSS feed ?
---
Désolé pour mon anglais plus que moyen. Je profite pour te saluer car j'ai eu l'occasion de suivre une formation Flex dispensée sur Paris il y a de ça quelques années et j'en garde un excellent souvenir.
Ton approche RIA me plait, du coup je vais suivre avec beaucoup d'attention tes recherches que je mène depuis quelques mois également.
Pour l'instant, je suis resté sur Backbone.js avec une librairie qui permet d'utiliser du Binding
Bonnes recherches