This three part article is the best documentation I have found for Handlebars (official docs and download).
More articles:
Handling Handlebars.js Like a Pro - Describes an intereting way to pre-compile templates for Dev and Prod use.
Handlebars.js Tutorial - Great overview and more.
Concepts:
<script type="text/x-handlebars-template" id="myTemplate">
var source = $("#contactRow").html();
var template = Handlebars.compile(source);
var htmlCode = template(data);
$('#destination').html(htmlCode);
Sometimes it's helpful to focus your work on a particular expression within a template. That's where blocks come in. Blocks are represented in Handlebars with the pound (#) symbol followed by an expression. Blocks end with a closing mustache, {{/expression}}.
If the expression given evaluates to an Array, Handlebars will iterate over each item in the Array, setting the current context to that item. Here's an example:
var data = { people: [
{name: "Alan"},
{name: "Allison"},
{name: "Ryan"}
], group: "Bloggers" };
<script type="text/x-handlebars-template">
<ul>
{{#people}}
<li>{{name}}</li>
{{/people}}
</ul>
</script>
Because blocks change the current expression context, Handlebars supports using the ../ expression to access parent contexts. So in the previous example, we could have used the expression ../group while iterating over each of the people to print out the name of the group:
<script type="text/x-handlebars-template">
<ul>
{{#people}}
<li>{{name}} - {{../group}}</li>
{{/people}}
</ul>
</script>
If a block's expression evaluates to anything other than an Array, Handlebars simply sets the context to the result of evaluating the expression. This can save a lot of typing when outputting several properties of an object:
var data = { person: {
firstName: "Alan",
lastName: "Johnson",
email: "alan@test.com",
phone: "123-456-7890"
} };
<script type="text/x-handlebars-template">
{{#person}}
<div>Name: {{firstName}} {{lastName}}</div>
<div>Email: {{email}}</div>
<div>Phone: {{phone}}</div>
{{/person}}
</script>
It can be easy at times to get confused about where you are in the stack in a Handlebars.js template. I usually keep a debug helper around to help me figure that out.
Handlebars.registerHelper("debug", function(optionalValue) {
console.log("Current Context");
console.log("====================");
console.log(this);
if (optionalValue) {
console.log("Value");
console.log("====================");
console.log(optionalValue);
}
});
You could then use that helper in any template like:
{{debug}}
or like:
{{debug someValue}}
and you'll see output in the JavaScript console letting you know what's going on:
Current Context
====================
email: "alan@test.com"
first_name: "Alan"
last_name: "Johnson"
member_since: "Mar 25, 2011"
phone: "1234567890"
stripeClass: "even"
__proto__: Object
Value
====================
Alan