Nelvin Driz
ndriz@exist.com
Handlebars.js
minimal templating on steroids
Who are the others?
Why use handlebars.js?
/人◕ ‿‿ ◕ 人\
Web Applications
Dynamic Interfaces
Cleaner and Simpler
Example
#Given a JSON Data
var data = { items: [{text: “Hello World”}, ... ]};

#Normal JS
var div   = document.createElement(“div”),
    items = data.item;
for(var i = 0; i < data.item.length) {
  div.append(items[i].text);
}

#With Handlebars.js
var html = “<div>{{#each items}}{{text}}{{/each}}</div>”;
var template = Handlebars.compile(html);
template.html(data);
General Details


 Started by Yehuda Katz
 Built upon {{ Mustache }} (Logic-less templating)
 Compiles templates into a function
 No Dependencies
Guidelines


Using jQuery v1.6.2
Using Handlebars.js 1.0.0 beta3
Templates are surrounded by:
  <script type=”text/x-handlebars-template” name=”x” id=”x”></script>
Quick Example
#Template
{{#person}}
  {{../birthday/month}}
{{/person}}

#Data
var data = {
   person : { name : "name" }
, birthday: { month: "month" }
};

#Output
month
Javascript Flow
/* Data */
var data = {
   person : { name : "name" }
, birthday: { month: "month" }
};

/* Get Template */
var html = $(“#selector”).html();

/* Compile */
var template = Handlebars.compile(html);

/* Generate HTML using template */
template(data);
{{Expression}}
{{Expression}}
Template
{{value}} {{fcn}} {{nothing}}
{{escaped}}
{{{notEscaped}}}

Data
var data = {
   value: “value”
, fcn : function() { return “function”; }
, escaped    : “<div>escaped<div>”
, notEscaped: “<div>not escaped</div>”
};

Output
value function  
&lt;div&gt;escaped&lt;/div&gt;
<div>not escaped</div>
{{Expression}}
 Simplest Dynamic Content
 Handlebar curly brace ( { / } )
 Contains (Value/Function/Nothing)
 Escapes Results by Default
   Use {{{Expression}}} to Unescape
   3 Pairs of Handlebars
Handlebars.Path/Nesting
Handlebars.Path/Nesting
#Template
{{#person}}
  {{../birthday/month}}
{{/person}}
{{person.firstName}} {{person/middleInit}}

#Data
var data = {
   person : { firstName : “name”
             , middleInit: “m”     }
, birthday: { month: "month" }
};

#Output
month
name m
Handlebars.Path/Nesting

{{this}} in a template means current context
dot ( . ) operator to inner context
deprecated forward-slash ( / )
dot dot ( .. ) operator to parent context
Chain-able
{{#Block}}{{/Block}}
{{#Block}}{{/Block}}


 start: Prepended by hash ( # )
 end: {{/Expression}} prepended by forward slash ( / )
 Change the context on the result of the {{#Expression}}
{{#if block}}{{/if}}

#Template
{{#if truthy}} truthy {{else}} falsy {{/if}}
{{#if falsy }} falsy {{else}} truthy{{/if}}

#Data
var data = {
   truthy: true
, falsy : false
};

#Output
truthy truthy
{{#unless block}}{{/unless}}
#Template
{{#unless truthy}} truthy {{else}} falsy {{/unless}}
{{#unless falsy }} falsy {{else}} truthy{{/unless}}
{{^falsy}} false {{/falsy}}
{{^zero }} truth {{/falsy}}

#Data
var data = {
   truthy: true
, falsy : false
, zero : 0
};

#Output
falsy falsy false
{{#each block}}{{/each}}
#Template
{{#each ul1}} {{this}}    {{/each}}
{{#each ul2}} {{li}}      {{/each}}
{{#each ul2}} {{this.li}} {{/each}}

#Data
var data = {
   ul1: [“li1”, “li2”]
, ul2: [{li: “li1”}, {li: “li2”}]
};

#Output
li1 li2
li1 li2
li1 li2
{{#with block}}{{/with}}
#Template
{{#with person}} {{firstName}} {{birthday}} {{/with}}

#Data
var data = {
   person: {
     firstName: “name”
   , birthday: “date”
   }
};

#Output
name date
Global Block Helpers
Special Parameters ( . / .. / this )
Built in block helpers:
  {{#each}} , {{#if}} , {{#unless}} , {{#with}}
Special Expressions:
  {{else}} Used for {{#if}} and {{#unless}}
  {{^expression}} just like {{#unless}} but not on zero
Custom Expression Helpers
Custom Expression Helpers

#Helper
Handlebars.registerHelper(“greet”, function(fN, lN) {
  return “Hello, “ + fN + “ ” + lN “!”;
});

#Template
{{greet “firstName” “lastName”}}

#Output
Hello, firstName lastName!
Custom Expression Helpers


Use Handlebars.registerHelper(“helperName”, fcn);
function(parameters, ... , block) {};
Call like an {{Expression}}
Custom Block Helpers
Custom Block Helpers
#Helper
Handlebars.registerHelper(“modulo”, function(n, block) {
  if((n % 2) == 0) {
    return block();
  } else {
    return block.inverse();
  }
});

#Template
{{#modulo 10}} even {{else}} odd {{/modulo}}
{{#modulo 3 }} even {{else}} odd {{/modulo}}

#Output
even odd
Custom Block Helpers

Use Handlebars.registerHelper(“helperName”, fcn);
function(parameters, ... , trueBlock, falseBlock) {};
function(parameters, ... , block) {};
  trueBlock ~ block | falseBlock ~ block.inverse
Call like a {{#Block}}
Hash=Arguments (Helpers)
Hash=Arguments (Helpers)
#Helper
Handlebars.registerHelper(“gate”, function(block) {
  if(block.hash[“key”] == “open”)
    return block();
});

Handlebars.registerHelper(“gate2”, function(block) {
  return block.hash[“key”];
});

#Template
{{#gate key=”open”}}open{{/gate}}
{{gate key=”open”}}

#Output
open
open
Hash=Arguments (Helpers)


key=value pairs
Accessible through block.hash object
Partials


 Use Handlebars.registerPartial(“partialName”, tmpl);
 The partial may be a String or a Compiled Template
 Use {{> partialName}} inside template
Extra : Debugger

Handlebars.registerHelper(“debug”, function(optValue) {
  console.log(“Context”);
  console.log(“=========”);
  console.log(this);

  if(optionalValue) {
    console.log(“Value”);
    console.log(“=========”);
    console.log(optValue);
  }
});
Extra: Listener

#Helper
Handlebars.registerHelper(“listener”, function(block) {
  $(“#selector”).html(block(this));
  return “”;
});

#Template
{{#listener}}listened {{value}}{{/listener}}
Resources

http://www.handlebarsjs.com/
http://yehudakatz.com/2010/09/09/announcing-
handlebars-js/
http://thinkvitamin.com/code/getting-started-with-
handlebars-js/
Questions?

Handlebars

Editor's Notes