Handlebars.js: Is there any way to render handlebars template from an external file?

Created on 13 May 2011  路  13Comments  路  Source: handlebars-lang/handlebars.js

I mean not from inline code.

Most helpful comment

You can keep your handlebars templates in a separate file and load via AJAX with this snippet (assumes 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);
            }               
        });         
    })()

All 13 comments

You can keep your handlebars templates in a separate file and load via AJAX with this snippet (assumes 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);
            }               
        });         
    })()

I have a template that is generic enough that I can reuse it several times, so I load it from the server with an AJAX call and stuff it into the page. This snippet (jQuery) may not be the best, but it's worked well for me so far.

_getTemplate: function () {
  var self = this, tmpl = self._findTemplate();
  if (tmpl.length === 0) {
    var response = $.get('/bling/get_template', {template: self.options.template},
      function (data) {
        self.template = data;
        if (self._findTemplate().length === 0) {
          $('body').append(self.template);
        }
      }
    );
  } else {
    self.template = tmpl;
  }
},
_findTemplate: function () {
  return $('body').find('#' + this.template_id);
}

I have this in a rails app, so the mustache template is a partial just like any other view file. This is all it takes to spit back the mustache template:

def get_template
  render :partial => "#{params[:template]}.mustache"
end

I agree that this would be great. ICanHaz.js has really good support for loading templates via Ajax, so perhaps some of the general design can ported. http://icanhazjs.com/

I threw together some code for this. It supports synchronous and asynchronous loading of templates (using jQuery.ajax).

/*
 * This decorates Handlebars.js with the ability to load
 * templates from an external source, with light caching.
 * 
 * To render a template, pass a closure that will receive the 
 * template as a function parameter, eg, 
 *   T.render('templateName', function(t) {
 *       $('#somediv').html( t() );
 *   });
 */
var Template = function() {
    this.cached = {};
};
var T = new Template();
$.extend(Template.prototype, {
    render: function(name, callback) {
        if (T.isCached(name)) {
            callback(T.cached[name]);
        } else {
            $.get(T.urlFor(name), function(raw) {
                T.store(name, raw);
                T.render(name, callback);
            });
        }
    },
    renderSync: function(name, callback) {
        if (!T.isCached(name)) {
            T.fetch(name);
        }
        T.render(name, callback);
    },
    prefetch: function(name) {
        $.get(T.urlFor(name), function(raw) { 
            T.store(name, raw);
        });
    },
    fetch: function(name) {
        // synchronous, for those times when you need it.
        if (! T.isCached(name)) {
            var raw = $.ajax({'url': T.urlFor(name), 'async': false}).responseText;
            T.store(name, raw);         
        }
    },
    isCached: function(name) {
        return !!T.cached[name];
    },
    store: function(name, raw) {
        T.cached[name] = Handlebars.compile(raw);
    },
    urlFor: function(name) {
        return "/resources/templates/"+ name + ".handlebars";
    }
});

Hi! This is outside of the scope of what Handlebars.js does. It'd be awesome if you'd like to create a library and share it (we'll add it to the readme). We're also working on a precompiler that will turn your templates into plain javascript so that you an load it with any normal javascript loading mechanism.

This should be documented some where in the README. It's a useful and important utility.

Lumbar is the tool that we are using to handle this. (also provides platform specific builds and stylus integration) http://walmartlabs.github.com/lumbar/

This is more of a build time solution than a runtime solution vs. the above.

How to disable handlebars.js cache?

I just finished this library to solve exactly this problem.

https://github.com/cultofmetatron/handlebar-helper

handlebar-helper link is broken.

@thinkbigthings I'm guessing this is @cultofmetatron's renamed repository:
https://github.com/cultofmetatron/jquery-autobars

I also wrote an entire extra module to solve this problem (on the server-side anyway): handlebars-generator

It's easier to keep it as a separate module. The handlebars compiler itself is better left synchronous and in-memory, rather than trying to load it down with file system issues.

I found this issue whilst Googling, and despite using the technique at the top of this issue, and the return being a string, Handlebars is still complaining that I'm passing an object, when it's actually a string.

Although loading templates is outside of the scope, to me it's a critical part of using a templating engine. As nearly everyone will keep different templates in different files.

My error was incorrect use of ajax to load the partials

Was this page helpful?
0 / 5 - 0 ratings

Related issues

aputinski picture aputinski  路  11Comments

stevenvachon picture stevenvachon  路  15Comments

robincsamuel picture robincsamuel  路  24Comments

dougwilson picture dougwilson  路  23Comments

matrym picture matrym  路  37Comments