Handlebars.js is a great tool for client side templates, but one thing that is a bit of a nag about Handlebars.js templates is the fact that the docs recommend you insert the templates as inline script tags. This can be a bit of an issue if you have a lot of views, since you probably don’t want to put them all on your page, or perhaps you have something more dynamic in mind.. Consider the implementation defined in the Handlebars.js docs:

<script id="entry-template" type="text/x-handlebars-template">
{{content}}
</script>

This can get out of hand quickly if you have multiple templates and it gets even worse if you want to reuse your templates across multiple files. The solution I came up with involves loading your templates via ajax. This allows you to organize your templates however you see fit but I personally prefer to lay them out like this:

/public_html/
/public_html/js/
/public_html/js/templates/
/public_html/js/templates/apple.handlebars
/public_html/js/templates/orange.handlebars
/public_html/js/templates/banana.handlebars

You can use the following code to load a handlebars template via ajax. (example assumes you use jQuery):

(function getTemplateAjax(path) {
    var source;
    var template;

    $.ajax({
        url: path, //ex. js/templates/mytemplate.handlebars
            cache: true,
            success: function(data) {
                source    = data;
                template  = Handlebars.compile(source);
                $('#target').html(template);
        }
    });
})()

Since we are loading via ajax you might want to rewrite your template loading function to utilize a callback like this:

(
	function getTemplateAjax(path, callback) {
		var source;
		var template;

		$.ajax({
			url: path,
				success: function(data) {
					source    = data;
					template  = Handlebars.compile(source);		

					//execute the callback if passed
					if (callback) callback(template);
			}
		});
	}

	//run our template loader with callback
	(getTemplateAjax('js/templates/handlebarsdemo.handlebars', function(template) {
                
		//do something with compiled template
		$('body').html(template);
	})()
)()
  • Kevin Hodges

    Just what I was looking for, saved me a whole bunch of time, cheers!

  • Anonymous

    glad it helped

  • Dwight_vietzke

    Yep, nice post. Just getting started with Handlebars and this got me the tie in to jQuery fast.

    Thanks again

  • MLesher

    Under this model, what does your handlebarsdemo.handlebars file look like? I am working with trying to set this up and have it mostly working, but handlebars is throwing an error on the compile method. If you could please post an example of what the template looks like, I would appreciate it. Thanks!

  • http://twitter.com/jordancooperman Jordan Cooperman

    Is the ‘source’ argument in callback supposed to be named ‘template’?

    • jblotus

      yes that was a mistake, thanks!

    • j_blotus

      yep that was a mistake, thanks!

  • Anonymous

    Are these examples actually working? To me it does not seem logical to make the templates (handlebarsdemo.handlebars) be the url used in the ajax call – shouldn’t this instead be the call to the WS returning the JSON? Also, where is the JSON data actually bound to the template?

  • Pingback: Handlebars.js – JavaScript templating engine baseado em Mustache » Pinceladas da Web - HTML5 Hard Coding and Bullet Proof CSS

  • greg

    thx but i get the following error via firebug:

    Error: You must pass a string to Handlebars.compile. You passed [object XMLDocument]

    So how does your template looks like?

    Greetz

  • JohnDesigns

    Hi! great article, 10 minutes ago I discover this plugin for jQuery https://github.com/CKGrafico/jQuery_HandlebarsJS/ very interesting, I think..

  • isaacalves

    Nice post! I’m struggling to have my handlebars related files organized.

    Now, you can’t have PHP inside a .handlebars file, like this:

    {{#each image_urls}}

    <img src="webroot; ?>{{this}}” alt=”">

    {{/each}}

    I have the same template across differenct .ctp (cake) files.

    Any idea of a workaround for that?

    • j_blotus

      two ways to deal with this. 1) pass in the image url to the hb template when rendering
      2) your server can still execute php in the .handlebars template (although mixing languages like this could be frowned upon).

      • isaacalves

        how do you pass a variable to a handlebars template when rendering? do you have to use partials? is there documentation for that? thank you