I mean not from inline code.
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.
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
Most helpful comment
You can keep your handlebars templates in a separate file and load via AJAX with this snippet (assumes jQuery):