Demo of Handlebars, and why you should consider a templating engine

This post is more than 2 years old.

For a while now I've been thinking I need to pick up, and start using, a JavaScript templating engine. I had used a jQuery-based one a few years back, but that project was abandoned and I've yet to really look what - if any - solution would work good for me. Another reason I've not found the time is that a majority of my JavaScript examples are small little demos built for blog posts. When I blog, I try my best to keep my code as simple as possible. I don't go all MVC just to demonstrate date formatting. It may not be real world, but it also keeps you focused on the topic I'm trying to discuss.

Today I made the time - and more specifically - made a demo. The demo is stupid. It's not even important. What is important is this:

If you've ever used JavaScript to build strings of HTML, you never realized just how much of a pain that is until you don't have to. You never realized how resistant you are to adding new features - or tweaking the design. You never realized how much you held back - just because of how much of a pain in the rear it was!

I'm probably being overly dramatic, but to me, it feels a lot like ORM. Yeah, it's simple to go into a database client, open a table, and add a new field. But when you can do all of that via code... it feels incredibly freeing. You feel yourself trying new and interesting things. In fact, the demo I'm going to show has about twice the features I was planning just because it was so damn easy to add.

That's how I feel today - and any day where my computer makes me smile is a good day. Ok, enough rambling.

I had heard about Handlebars from various people. It's also the templating engine that Ember.js uses. Handlebars works by allowing you to define templates using simple script blocks, so for example, you can write your template in your document like so:

You then use the Handlerbars API to create a template out of the block, apply data to it, and then render it to screen. It's all relatively simple, but the docs don't necessarily do a great job I think of demonstrating simple examples in "full" pages so you can see things in context. Here is a trivial example:

Notice how I've got a simple template block on top. If you've never seen Handlebars before, or any JavaScript templating engine, you can probably guess which portions of the block represent dynamic portions and which represent static text.

I've got a simple form with a button bound to a simple click listener. Looking at the JavaScript, you can see that first I have to grab the HTML from the template block. I then compile this. This gives me a template that I can reuse to generate output.

My form has a simple click handler. When you hit the button, I pass the values to my template and grab the HTML out of it. You can run this demo here:

https://staticraymondcamden.com/demos/2012/apr/19/test1.html

Of course, not every template will be a simple set of keys and values. Your template may also need to be dynamic based on the values passed in. Let's look at another example that makes use of both lists and conditionals.

In our template, we've got two things going on here. First is a conditional that checks if "things" is a truthy value (truthy being one of the things that make JavaScript so fun). Within the true part of the conditional we use an each block to enumerate over a set of values.

If you scroll down to the HTML/JavaScript, you can see I'm just asking for you to enter a list of things you like. That value is split into an array and passed (if there were values) to the template. Demo this below..

https://static.raymondcamden.com/demos/2012/apr/19/test2.html

Let's look at one more example. One of the cooler aspects of Handlebars is that you can add custom functions to the engine. For example, you could write a cowbell function that wraps your results in the beautiful rocking sounds of the cowbell. Ok, maybe not that. But what about something a bit complex - like converting an email address into a MD5 hash that could be used for Gravatar? Yeah - no way that would work...

Notice in the template we have one simple value, email, and then this: gravatar email. This isn't something built into Handlebars, but rather, injected via the registerHelper function you see in the main script block of the page. You can demo this here:

https://static.raymondcamden.com/demos/2012/apr/19/test3.html

Ok. Time to kick it up a notch. Many moons ago Jason Dean introduced me to the ComicVine API. This is a free API that provides access to their pretty deep database of comic book data. Unfortunately their API isn't very well supported and the documentation is missing a few important details. But I was able to take their service and build the following.

This application uses JSON/P and the ComicVine API to let you search against their character database. A good search string is "spider". Obviously it doesn't have everything in there, but it's fun to see what's there. Oh yeah - be sure to search for "Beyonder" - the best thing to come out of Marvel in the 80s. You can demo this here:

Raymond Camden's Picture

About Raymond Camden

Raymond is a senior developer evangelist for Adobe. He focuses on document services, JavaScript, and enterprise cat demos. If you like this article, please consider visiting my Amazon Wishlist or donating via PayPal to show your support. You can even buy me a coffee!

Lafayette, LA https://www.raymondcamden.com

Archived Comments

Comment 1 by Raymond Camden posted on 4/20/2012 at 2:01 AM

By the way - here is a good presentation on JavaScript templating engines. Lots of options:

http://www.slideshare.net/g...

Comment 2 by Adrian J. Moreno posted on 4/20/2012 at 4:15 AM

We just started talking about Handlebars, plus you answered the question, "where can I find a comic book database?" for me.

2-for-1!

Thanks.

Comment 3 by Raymond Camden posted on 4/20/2012 at 5:24 AM

I wrote this post just for you. Honest. :)

Comment 4 by existdissolve posted on 4/20/2012 at 7:14 AM

This is really cool, and it's nice to see a pretty intuitive convention for templating. I also like the JSON/P integration :)

Just curious, but have you played around with the templating in ExtJS ever?

Comment 5 by William Ukoh posted on 4/20/2012 at 12:32 PM

Thanks for the post

Comment 6 by Roberto posted on 4/20/2012 at 12:36 PM

Spry was too cool to survive? :-)
thanks ray :-)

Comment 7 by Raymond Camden posted on 4/20/2012 at 3:30 PM

@Exitdissolve: No - I'm not much of a fan of Ext. It is -very- powerful, but I don't like _how_ it works if that makes sense.

@Roberto: Heh, well, it was a great effort. If you ever look at Angular, it is similar (although Angular has gone far further).

Comment 8 by Manithan posted on 4/20/2012 at 5:13 PM

i have used handlebars little bit and i liked it. now i like AngularJS which comes with everything the main part i like about AngularJS templates is that it has two way binding which makes life lot easier. After played lot with other templates Angular is the one got in to me and it is all HTML

Comment 9 by Kevin C. posted on 4/20/2012 at 5:18 PM

Demos don't appear to be working for me. Firebug showing different errors for each one.

Comment 10 by Raymond Camden posted on 4/20/2012 at 5:25 PM

Kevin - I see that. Give me a sec and I'll fix it.

Comment 11 by Raymond Camden posted on 4/20/2012 at 5:30 PM

Heh, interestingly enough - given a div with id X, Chrome allows for

X.innerHTML = "...";

whereas Firefox does not. I just fixed it - and made it "more proper" by doing

document.querySelector("#X").innerHTML = "...";

Thanks for the report, Kevin.

Comment 12 by Phillip Senn posted on 4/20/2012 at 6:34 PM

I am assuming you have decided to use vanilla JavaScript so as not to be tied to a particular library. I chose jQuery because Internet Explorer requires attachEvent('onclick'...) instead of AddEventListener('click'...). My feeling is that if JavaScript libraries had not been written, then everyone would have to write their own because you sure don't want to put an if/then block around every time you declare an event.

I pulled up your example in IE9 and it didn't work using (Alt+9) or (Alt+8).
It goes without saying that the only time I pull up Internet Explorer is just to see how my users would see it.
But JavaScript being so brittle is why it's frustrating - you get something that works, and then it doesn't work in another environment.

Comment 13 by Raymond Camden posted on 4/20/2012 at 6:43 PM

I choose not to use jQuery in these demos just because I'm trying to do more things on my own. I recognize that it will not always be cross-browser compatible. Frankly - I'm ok with that for demos. I do want Chrome/Firefox to work, but everything else I'm not so concerned with.

I'm not against libraries like jQuery. I love jQuery. At the same time, I'm trying to improve my JavaScript skills so I'm trying to do more on my own without the training wheels of jQuery.

Comment 14 by Phillip Senn posted on 4/20/2012 at 7:03 PM

Hmmm... That's a bit of a conflict. Are you posting the blog entry for the readers or yourself? I know the answer is "a little of both". That you often refer back to previous blog posts or have even posted some things for the purpose of writing it down. But if you have to make disclaimers like "This works for all the standard browsers, but might not work once you deploy to production", then that's doing a bit of a disservice to your readership.

I want to argue again the idea that it's a crutch. The fact is that JavaScript is broken. CSS is broken too as far I know. Developers are wasting too much time with polyfills and shims and hacks to get around browser inconsistencies. Don't think of it as a crutch. Just think of it as a couple of routine you may have written yourself that say something like "If (this feature is support) { use this feature } else { use this polyfill or shim or hack }

Comment 15 by Raymond Camden posted on 4/20/2012 at 7:18 PM

We will have to agree to disagree. I think a demo not working in IE is not a disservice to my readers. A demo is not a production site with hours of QA and UX testing. A demo is just that - a demo. If you view my blog entries as something that is always 'production ready', then I think you are reading way too much into what should be just simple examples. Frankly, I don't want that kind of pressure when I blog.

As for 'crutch' - I was perhaps being too strong. There are things I use jQuery for that I can do easily myself. The biggest one being $("...") for example. Ditto for the jsonp support which wasn't difficult at all. I'm not arguing against using jQuery. I'm simply saying you don't have to use it all the time.

Comment 16 by Adrian J. Moreno posted on 4/20/2012 at 7:29 PM

"But JavaScript being so brittle is why it's frustrating - you get something that works, and then it doesn't work in another environment."

Hang on, there's a typo:

"But Internet Explorer being so brittle is why it's frustrating - you get something that works, and then it doesn't work in another environment."

There you go. :P

Comment 17 by Brad Newman posted on 4/20/2012 at 9:36 PM

Ray, I had no clue about templating engines.. Thanks for the post.. Or, maybe not as I will be consumed with research for the next few days. ;-)

Comment 18 by GMS posted on 4/25/2012 at 9:35 AM

With the irony that coldfusion is a template engine, aside. Templating engines are best way to improve your code's readbility and maintainability. We use another take on mustache called Goatee [https://github.com/owenalle...]. The advantage of this system is you can reuse templates to be used from the Javascript implementation or in Coldfusion. If anyone is interested in VIMEO tutorial let me know

Comment 19 by Adrian J. Moreno posted on 4/27/2012 at 3:09 AM

Working this into an internal application. Ridiculously simple.

Comment 20 by Phillip Senn posted on 5/1/2012 at 7:52 PM

Darn it! I had this working relatively quickly but then I lost it (now it's not working). So, if I SELECT from an html5 openDatabase, then I get a result which has result.rows.item(0), result.rows.item(1), etc.

So how do I call mustache again?
I've tried:

template(result);
template(result.rows);
template(result.rows.item);

Comment 21 by Raymond Camden posted on 5/1/2012 at 7:56 PM

html5 openDatabase? I don't know what that is. Do you mean WebSQL? If so - the Handlebars may not like the form of the data. You may want to rewrite it as a simple array of structs and pass that.

Comment 22 by Phillip Senn posted on 5/1/2012 at 9:25 PM

Here is my http://jsfiddle.net/Phillip... where I drop, create, insert, select and (try to) display the result from the select.

Maybe I have to do some kind of $.makeArray or something.

Comment 23 by Raymond Camden posted on 5/1/2012 at 10:23 PM

No idea what makeArray is - but - remember KISS. I'd just make a new array (var data = []), and loop over your SQL results and add them manually. Then pass data to handlebars.

Comment 24 by Phillip Senn posted on 5/1/2012 at 11:50 PM

OK, yeah, that helped me getting it to work right.
http://jsfiddle.net/Phillip...

Although I'm not happy with having to loop over the result because I have a sneaking suspicion that it's not required, but it does work.

I really appreciate it!
Thank you very much!

Comment 25 by Raymond Camden posted on 5/1/2012 at 11:53 PM

Glad you got it!

Comment 26 by stegoste posted on 5/5/2012 at 1:35 AM

I have one website about <a href="http://www.medialinkwireles...">medialink wireless n router</a> and I would like to try handlebars, but I'm not sure if I will succeed because the site is developed in wordpress...

Comment 27 by Raymond Camden posted on 5/5/2012 at 1:40 AM

You would need to edit the code I assume.

Comment 28 by phani kiran.M posted on 11/20/2013 at 7:32 PM

hi all,
I just started working now on handlebars.I m facing problem while compiling handlebar template file into .js with minified version file,The newly crerated file is starting '!' symbol it is observed after opening the file , the newly created js file which browser is not accepting.how can i fix this issue in 64-bit machine.can anyone help me on this.

Regards,
phanikiran

Comment 29 by Raymond Camden posted on 11/21/2013 at 2:24 AM

Not sure what to suggest here. When I did my tests with Handlebars I didn't try minimizing the compiled templates. I'd try their Google group (pretty sure they have one).

Comment 30 by prad posted on 12/14/2013 at 11:10 PM

Hi am working on a application, where server is giving me response of type float i.e xxx.yy I need to display this xxx.yy as xxxhyy

example: from server response---->112.45
output should be---------->112h45

How do i do this please help me

thanks in advance....

Comment 31 by Raymond Camden posted on 12/15/2013 at 12:29 AM

You need a block helper. See: http://handlebarsjs.com/blo...

Comment 32 by siva posted on 1/15/2014 at 5:15 PM

in ie8 handle bar js is not working

Comment 33 by Raymond Camden posted on 1/15/2014 at 5:25 PM

From what I can see, it should work in IE8. Can you please specify what error you are getting? This may be an issue for the Handlebars team though.

Comment 34 by sakthi posted on 10/5/2015 at 8:51 AM

Hi I am new for this, how to prepare popup window login form with validation? anybody having sample code.

Comment 35 (In reply to #34) by Raymond Camden posted on 10/5/2015 at 10:13 AM

This question doesn't really apply to the article, does it? You can find a simple popup/modal code in Bootstrap.

Comment 36 by Mark Lottes posted on 12/16/2015 at 3:17 AM

Thank you so much. Exceptional write up. I have literally read over a dozen articles today looking for examples and your is the only one that has been helpful. Great job.

Comment 37 (In reply to #36) by Raymond Camden posted on 12/16/2015 at 12:50 PM

This is an old post, but I'm glad it was helpful. As an FYI, I have an entire course on client-side templating for sale on oreilly.com. You can get to it from the "About Me" link above.

Comment 38 by Echeban posted on 9/13/2017 at 4:16 PM

How can I use handlebarsjs to emulate the most basic feature of ASP Master Pages, just to have a common Header, Footer, and Menu for all pages?

Comment 39 (In reply to #38) by Raymond Camden posted on 9/15/2017 at 3:01 PM

Well keep in mind Handlbars can be used in two contexts - either in the client side as I described here or on the server side with Node. On the client-side, what you describe doesn't really make sense. On the server side, you could use layouts with Handlebars and get the behavior you want.

Comment 40 by Stepan Kolomiets posted on 6/21/2018 at 9:49 AM

Hi guys, I need your advice. If, for example, I have 5 sections where I should include header which is the same, should I use Handlebars or there are other better solutions to keep up with DRY rule?

Comment 41 (In reply to #40) by Raymond Camden posted on 6/21/2018 at 12:55 PM

I'm not 100% sure I understand what you are asking. Handlebars lets you define, and reuse, a template. So that header you defined could be a template used in multiple places. Look at Partials, for example.

Comment 42 (In reply to #41) by Stepan Kolomiets posted on 6/21/2018 at 8:27 PM

Thanks, it's exactly what I'm looking for!