Last week we looked at the basics of using Handlebars.js. We learned how to write a basic template to loop over a list of people. This week we’ll build on that by learning about using Handlebars’ built-in helpers, writing and using partials, and writing custom helpers. Let’s get started!
Built-In Helpers
Handlebars includes a few built in helpers that make life easier. They are {{#each}}
, {{#if}}
, and {{#unless}}.
The each Helper
The {{#each}}
helper iterates over each item in an array. Here’s an example.
The above template would iterate over each item in the array named people and output the content of the block.
The if Helper
The {{#if}}
helper does just what you’d expect. It allows you to implement an if block in your code. The if
helper outputs the block that it contains if the value given to it is truthy.
One tricky aspect of the helper, though, is that Handlebars doesn’t support conditional statements, so code like {{#if x > y}}
isn’t possible. That’s on purpose. Our take is that any tricky logic like that can be wrapped up into a helper to make sure that your template stays nice and clean.
Here’s an example:
That template would only output the inside of the block if people was truthy, so it wouldn’t output if people was null
, 0
, false
, or undefined
. Probably a more appropriate if statement in the above example would be {{#if people.length}}
, so that the block would also not be displayed if a people array is present, but empty.
The unless Helper
The {{#unless}}
helper is basically just the opposite of if. It only outputs the contained block if the given expression is false. So, for example:
The above template would only output the sentence There aren’t any people if people.length
evaluates to a falsy value like null
, 0
, false
, or undefined
.
The else Expression
Handlebars.js includes a special expression, {{else}}
, that can be used with any block helper to represent what should be output if the given expression evaluates to a falsy value. Here’s an example of how to use it:
Partials
Partials come in handy when you have a chunk of a Handlebars.js template that you need to use in a few different contexts. The Handlebars.registerPartial
method registers a partial. It takes the name of the partial as its first argument and either a template source string or a compiled template as its second argument. The fact that it accepts a compiled template as the second argument is actually pretty useful. That allows you, for example, to use the partial in a loop that outputs a list but also append items to the list later using the partial’s template function.
To use a partial from a template, simply include {{> partialName}}
. Here’s an example of using a partial:
Writing Customer Helpers
One of our major motivations in writing Handlebars.js rather than just using mustache.js was to allow users to define global helpers. Handlebars supports defining both expression and block helpers.
Custom Expression Helpers
To register an expression helper, use the Handlebars.registerHelper
method. It takes the name of the helper and the helper function as arguments. Handlebars.js takes whatever is returned from the helper function and writes it out to the template, so be sure to always return a string from your custom helpers.
To write an expression helper function to output a formatted phone number, you could define the following helper:
Handlebars.registerHelper("formatPhoneNumber", function(phoneNumber) {
phoneNumber = phoneNumber.toString();
return "(" + phoneNumber.substr(0,3) + ") " + phoneNumber.substr(3,3) + "-" + phoneNumber.substr(6,4);
});
You would use the formatPhoneNumber
helper in a template like this:
{{formatPhoneNumber phoneNumber}}
Custom Block Helpers
Custom block helpers are also registered with the Handlebars.registerHelper
method. When a helper is used with a block, Handlebars will pass the contents of the block compiled into a function to the helper. If an {{else}}
expression is found in the block Handlebars will also pass the contents of the else
block to the helper as well.
Here’s an example block helper that iterates through an array, letting the contents know whether it’s an even or odd row. The helper takes the array to iterate over, the css class name for even rows, and the css class name for odd rows as arguments. You’ll also notice the compiled template function fn
for the contents of the block and the compiled else block function, elseFn
are arguments to the helper function. The helper simply adds a property named stripeClass
to each item in the array as we iterate over it so that we can output that class name within the block. If the array given is falsy or empty the helper just returns the contents of the else block.
Handlebars.registerHelper("stripes", function(array, even, odd, fn, elseFn) {
if (array && array.length > 0) {
var buffer = "";
for (var i = 0, j = array.length; i < j; i++) {
var item = array[i];
// we'll just put the appropriate stripe class name onto the item for now
item.stripeClass = (i % 2 == 0 ? even : odd);
// show the inside of the block
buffer += fn(item);
}
// return the finished buffer
return buffer;
}
else {
return elseFn();
}
});
You would use the stripes helper in your template like this:
{{#stripes myArray "even" "odd"}}
... code for the row ...
{{else}}
There aren't any people.
{{/stripes}}
See It In Action
I actually wrote up a quick sample project that uses all of the techniques I've describe here. You can check that code out on GitHub or download a zip file of the source.
There's More!
There's a lot going on with Handlebars.js helpers, so we've got at least one more article worth of content to cover. Next week I'll show you how to do some neat tricks with the internals of how Handlebars.js blocks work. Please feel free to email me at alan@carsonified.com if you have any questions and I can cover those as well.
Nice Artical
人気スーパーコピーブランド時計激安通販専門店私達は長年の実体商店の販売経験を持って、先進とプロの技術を持って、高品質のスーパーコピー時計づくりに 取り組んでいます。最高品質のロレックス時計コピー、カルティエ時計コピー、IWC時計コピー、ブライトリング時計コピー、パネライ時計コピー激安販売中商品の数量は多い、品質はよい。海外直営店直接買い付け!★ 2015年注文割引開催中,全部の商品割引10% ★ 在庫情報随時更新! ★ 実物写真、付属品を完備する。 ★ 100%を厳守する。 ★ 送料は無料です(日本全国)!★ お客さんたちも大好評です★ 経営方針: 品質を重視、納期も厳守、信用第一!税関の没収する商品は再度無料にして発送します http://www.ooobrand.com/bags/bv/index.html
スーパーコピーブランド格安販売店はこちらへ!品々の激安価格に持ったスーパーコピーブランド 代引きの新作はお客様に提供されます。安心、迅速、確実、お客様の手元にお届け致します。★弊社は9年の豊富な経験と実績を持っております。★一流の素材を選択し、精巧な作り方でまるで本物のようなな製品を造ります。★品質を重視、納期も厳守、お客様第一主義を貫きは当社の方針です。★驚きの低価格で商品をお客様に提供致します!★早速に購入へようこそ! http://www.ooowatch.com/tokei/vuitton/index.html
人気スーパーコピーブランド時計激安通販専門店私達は長年の実体商店の販売経験を持って、先進とプロの技術を持って、高品質のスーパーコピー時計づくりに 取り組んでいます。最高品質のロレックス時計コピー、カルティエ時計コピー、IWC時計コピー、ブライトリング時計コピー、パネライ時計コピー激安販売中商品の数量は多い、品質はよい。海外直営店直接買い付け!★ 2015年注文割引開催中,全部の商品割引10% ★ 在庫情報随時更新! ★ 実物写真、付属品を完備する。 ★ 100%を厳守する。 ★ 送料は無料です(日本全国)!★ お客さんたちも大好評です★ 経営方針: 品質を重視、納期も厳守、信用第一!税関の没収する商品は再度無料にして発送します
[url=http://www.gginza.com/wallet/louisvuitton/index.html]最も美しいスーパーコピー,超格安ブランド時計コピー激安通販専門店!ブランド品に憧れて、予算オーバーし、諦めなければならないことがありましたか。スーパーコピー品が一番いいチョイスだ思います。少しのお金でも、世界中一番人気を持つブランド品、貴族しか買えない贅沢品がゲットできます。素敵な外観と実用性に優れたブランド コピー バッグ,,スーパーコピー財布,スーパーコピー 代引き,エルメス コピー,ルイヴィトン 財布、ルイヴィトン バッグ、ベルトなどの逸品はお客様に提供します。誰でもブランド品を手に入れられるのは弊社の経営理念です。当店の最大目標はお客様が安心してお買い物が出来き、お客様の頼りになるお店を目指す事ことです。お洒落な貴方はきっとこのチャンスを見逃しなくよ![/url]
スーパーコピーブランドなら当店で!
[url=http://www.brandiwc.com/brand-47-copy-0.html]エルバーキンコピーエルメスバーキン30コピーエルメス ボリード47,エルメス バッグ 名前,エルメス ネクタイ ピンク エルメス クラッチバッグ,エルメス バッグ コピー,エルメス バーキン コピー エルメス 財布 ダミエ オークション,エルメス ヨーロッパ,エルメス エールライン エルメス クラッチ激安通販、高い品質、送料無料。バーキン25コピー、バーキン30コピー、バーキン35コピー、バーキン40コピーなど世界中有名なブランドレプリカを格安で通販しております。N級品スーパーコピーブランドは ブランドスーパーコピー超N品エルメスバッグ,エルメス バーキン25 , バーキン30.バーキン35.バーキン40. エルメス(HERMES) ケリー[/url]
Here is big library of handlebars helpers http://assemble.io/docs/helpers/index.html so you can see examples of how they work. The library was created for http://assemble.io but the helpers can be used in any project.
Awesome.. This article sloves my problem in register helper..
Thanks..
Thanks the zip examples were very helpful.
I notice that the registerHelper in Handlebars 2011 now takes “options” instead of “fn”. You now use fn as options.fn.
Handlebars.registerHelper(“stripes”, function(array, even, odd, fn){
…
buffer += options.fn;
…
}
This seems to have a more robust backbone than the unofficial official jquery template system ($.tmpl) but I’ll wait to check out the documentation first. 🙂
Awesome, thanks!
Great article, but just 2 questions.
1. When would you use handlebars.js? Website? Widgets? Webapps? …
2. What about SEO?
regards
Vic
Hey Vic – great questions!
1. I’ve primarily used handlebars.js on really dynamic apps – think GMail type apps. If you’re already doing everything with XHR it’s a great fit because it’s way easier to write Handlebars templates than to generate html or dom elements yourself.
2. You’ll want to really think through the consequences of using handlebars.js. Content that you’re generating on the client side isn’t going to be indexed, but a lot of times that’s not all that important anyway. Would you use it for a public page on a marketing site? Probably not. Would you use it for a part of your app that’s already password protected? Go for it!
Really great question and answer about the implications with indexing.
Alan, this may be a ridiculous question, the JavaScript code blocks where you define the type as text/x-handlebars-template. Do these have to reside embedded in the actual page or can they be separate JS files?
I was wondering how to do this too. How can we move this embedded templates into separate files and just include them as scripts so we can have unobtrusive templates?
You can load the template asynchronously.
function getTemplateAjax(templateName, $target, context) {
var source, template;
jQuery.ajax({
url: ‘/path/to/template/’+templateName+’.mustache’,
cache: true,
success: function (data) {
source = data;
template = Handlebars.compile(source);
$target.html(template(context));
},
error: function () { console.log(“Aw, snap.”); }
});
}
// simple use case.
getTemplateAjax(“TemplateName”, jQuery(“body”), data);