Handlebars on the server
Handlebars is my view engine of choice in NodeJS. I like how it’s just HTML with curly braces and some helpers, as opposed to EJS and Jade which look significantly different to HTML. If you haven’t used Handlebars before, here’s what a simple template looks like:
<div class="entry">
<h1>{{title}}</h1>
<div class="body">
{{body}}
</div>
</div>
When building an Express web app, I use express3-handlebars to set up the plumbing to use Handlebars as a view engine. It’s written by my good friend and colleague, Eric, who’s one of the best engineers that I’ve ever met. I highly recommend it. You can set it up fairly easily through npm.
npm install express3-handlebars
Check out the basic usage section for information on how to set it up within Express.
Handlebars on the client
If you use any JavaScript MV* framework (BackBoneJS, EmberJS, YAF, etc), you probably need a template library on the client-side too. Handlebars plays well with all of these frameworks. One of the great things about using Handlebars on the client is that you can share templates between the client and the server. You can do this by having storing templates in partials, and then using those partials both on the server, and through <script>
tags on the client.
Client-side templates when using Handlebars on the server
If you’re using Handlebars on the client and the server, you’ll run into this issue where the client-side templates will be parsed by the view engine on the server. For example, you may have a file like this:
<h1>My Page Title</h1>
<!-- This template should be transformed into HTML by the server -->
<div id="photoList" class="pure-g">
{{#each photos}}
<div class="photo pure-u-1-12" data-photo-id="{{id}}">
<img class="pure-u-1" src="{{src}}">
</div>
{{/each}}
</div>
<!-- This template should not be touched. It's for the client -->
<script type="text/x-handlebars" id="lightbox-template">
<img class="lightbox-image" src="{{large}}">
<div class="lightbox-meta">
<a class="pure-button lightbox-link" href="{{url}}">View on Flickr</a>
<button class="pure-button lightbox-link lightbox-hide">Hide</button>
</div>
</script>
When you view this on the browser, the tags ({{..}}
) within <script id="lightbox-template">
will be parsed out. You’ll get something like this, which is useless:
<!-- I can't use this template on the client anymore!! -->
<script type="text/x-handlebars" id="lightbox-template">
<img class="lightbox-image" src="">
<div class="lightbox-meta">
<a class="pure-button lightbox-link" href="">View on Flickr</a>
<button class="pure-button lightbox-link lightbox-hide">Hide</button>
</div>
</script>
Fortunately, the fix for this is very simple, albeit not documented anywhere. Just add a \
in front of all the opening tags ({{
). The \
will be parsed out during the compilation step, and you’ll have a perfectly usable template on the client.
<!-- Add a \ before the handlebars -->
<script type="text/x-handlebars" id="lightbox-template">
<img class="lightbox-image" src="\{{large}}">
<div class="lightbox-meta">
<a class="pure-button lightbox-link" href="\{{url}}">View on Flickr</a>
<button class="pure-button lightbox-link lightbox-hide">Hide</button>
</div>
</script>
Kudos to Eric for coming up with this solution!
Checkout My2ndGeneration, it’s a handlebars based Code Generator, it’s 100% free, runs in the cloud or yes, there’s even a desktop version (yep, handlebars in a fat client). See http://www.my2ndgeneration.com/
Thanks so much – the \ trick saved the day!!!
I am liking the idea of using handlebars in Node and on the front end with Backbone – but the issue of the server pre-parsing the handlebar expressions was killing me!
No problemo!
Hi there, thanks for the info.
I use handlebars with backbone on the client side, and now I’m just beginning myself to work with Express and I’ve just found that Express 4 has arrived. Will this solution be still aplicable to Express 4 or it’s version 3 specific? Thank you.
It can work with Express 4. Check out my Node Boilerplate project, which sets up all this for you. https://github.com/tilomitra/node-boilerplate
Hi thanks for info.
I am new to handle bars.
I used your technique, works absolutely fine on client side but i need to do a date formatting. I am using this code.
\{{datetime created_at format=”DD/MM/YYYY”}}
gives me Uncaught Error: Missing helper: ‘dateFormat’
Please help me resolve this issue.
Thanks in advance!
Check out https://github.com/elving/swag
Hi Tilo, do you run into the problem of sharing hbs helper between client and server with this setup boilerplate, I find it hard to share it without duplicate the code, would like to hear if you have some insights, thx!
Yes, I’ll add a new post on how to share partials between the client and server. Stay tuned.
Yi, check this out: https://github.com/tilomitra/node-boilerplate/releases/tag/v2.1.1
Thank you so much!
Just What I have found for a long time…Thank U very much
Awesome…saved my day!