Problem with loading handlebar template with require js
Hi, I was using require.js text plugin to pull in html templates in my backbone app, the template engine I used is the one that comes with underscore/backbone, and things were working fine. I wanted to switch to handlebars template engine while continue using require js for module management, so I downloaded this plugin, but I am having tourble getting it to work.
I am on Fedora, using require-2.1.2. I downloaded require-handlebars-plugin-master. I put Handlebars.js and hbs.js in my js/lib directory and i18nprecompile.js and json2.js in lib/hbs directory. Handlebars.js in this plugin seems a little different than the one on handlebars site, in that it looks to be AMD enabled so I asume I don't need the shim.
In my index.html I have:
Here is my main.js
baseUrl: "./static/js/", paths: { jquery: 'lib/jquery-1.8.3.min', underscore: 'lib/underscore-1.4.3.min', backbone: 'lib/backbone-0.9.2.min', text: 'lib/text-2.0.3',
Handlebars: 'lib/Handlebars',
hbs : 'lib/hbs',
handlebars : "lib/Handlebars",
i18nprecompile : "lib/hbs/i18nprecompile",
json2 : "lib/hbs/json2",
bootstrap : 'lib/bootstrap'
},
shim: {
underscore: {
exports: "_"
},
bootstrap: {
deps: ['jquery']
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
}
}
......
And in my view, I have
define(function(require) { var $ = require('jquery'), _ = require('underscore'), Backbone = require('backbone'), Handlebars = require('handlebars'), hbs = require('hbs'), ClusterRowTemplate = require('hbs!app/mywork/templates/MyRowTemplate.hbs'); //ClusterRowTemplate = require('text!app/mywork/templates/MyRowTemplate.html');
var row = Backbone.View.extend({
//template: _.template(MyRowTemplate),
template: Handlebars.compile(MyRowTemplate),
....
The first issue I have is that in require config, I have to list both Handlebars and handlebars
Handlebars: 'lib/Handlebars', handlebars : "lib/Handlebars",
Otherwise, browser loads static/js/lib/Handlebars.js successfully, but then it tries to load static/js/Handlebars.js which will fail.
So I added both in require config, then I get the error of Uncaught Error: Load timeout for modules: hbs!app/mywork/templates/MyRowTemplate.hbs_unnormalized2,Handlebars
Although I can see Handlebars.js and hbs.js got pulled down.
Is there anything I mis-configured? Any help is greately appreciated.
Missed one line: In my index.html I have:
could this issue be related to issue #73 ?
my index.html just says look at static/js/main.js
Any chance you can put this on a public web server. The bad thing about sharing require-plugins is that anything complex gets difficult when people have different folder structures. It's likely some little thing I didn't make flexible enough.
I have deployed 2 sample projects on my x10 public server, the first one uses underscore's template with require js text plugin (see MainRouter), which works and you can see it says "Hello iyip"
http://ireneyip.x10.bz/MyProj/
The second one uses handlebars template with require js hbs plugin (all I did is in MainRouter uncomment the 2 code blocks for handlebars in define and showGreeting, and commentted out corresponding lines using text plugin), When I access
http://ireneyip.x10.bz/MyProj-hbs/
I got this error : Uncaught Error: Load timeout for modules: hbs!app/work/templates/GreetingTemplate.hbs_unnormalized2,Handlebars and there is no greeting printed out.
Also in main.js, I need both
Handlebars: 'lib/Handlebars',
//somehow both Handlebars and handlebars are needed
handlebars : "lib/Handlebars",
Otherwise, browser tries to load Handlebars at non-existing location.
Thanks for your help!
There is a 5-10 second delay before the handlebars error message shows up in the console when accessing http://ireneyip.x10.bz/MyProj-hbs/
Hmm. Digging into this now. It seems like the problem exists before hbs. The only reason I say this with confidence is that the hbs.js file is being loaded, but the module is never run. If you breakpoint on the define it will run, but if you breakpoint on the first line of the function, it never reaches there. I'll dig a little deeper and see if I can't find it.
The first thing I notice is that you're using the hbs plugin like it's the 'text' plugin. The whole niceness of the hbs plugin comes from the fact that you don't have to compile each time (and that it precompiles automatically at build), and it resolves its own dependencies.
In your file you've got:
define(function(require) {
var BaseRouter = require('base/routers/BaseRouter'),
//use handlebars template
Handlebars = require('handlebars'),
hbs = require('hbs'),
GreetingTemplate = require('hbs!app/work/templates/GreetingTemplate.hbs');
//use underscore template
//GreetingTemplate = require('text!app/work/templates/GreetingTemplate.html');
var MainRouter = BaseRouter.extend({
routes: {
"greeting" : 'showGreeting'
},
showGreeting: function() {
var data = { name : 'iyip'};
//use handlebars template
var compiledTemplate = Handlebars.compile(GreetingTemplate);
var tplHtml = compiledTemplate(data);
$("#content").html(tplHtml);
}
});
return MainRouter;
});
First, you don't have to explicitly require plugins, second, you don't always use extensions on plugins.
define(function(require) {
var BaseRouter = require('base/routers/BaseRouter'),
GreetingTemplate = require('hbs!app/work/templates/GreetingTemplate');
var MainRouter = BaseRouter.extend({
routes: {
"greeting" : 'showGreeting'
},
showGreeting: function() {
var data = { name : 'iyip'};
//use handlebars template
var tplHtml = GreetingTemplate(data);
$("#content").html(tplHtml);
}
});
return MainRouter;
});
Can you try something like that? (note, the return value of using the hbs plugin is an executable function.)
I updated MainRouter.js to be above on my x10 server, but still saw the same error (after clearing cache) when accessing
http://ireneyip.x10.bz/MyProj-hbs/
Uncaught Error: Load timeout for modules: hbs!app/work/templates/GreetingTemplate_unnormalized2,Handlebars
I have shared the project at https://docs.google.com/open?id=0B2ivLI2ptnZsSW9GelVLZWkxaUU
You can download it if that helps. (it is a zip not a tar.gz, but I tried the project on both linux and window and had the same issue). I think it is most likely some path issues. I looked into your demo project again, in demo.html, there is
paths : { 'hbs' : '../hbs', 'handlebars' : '../Handlebars', 'underscore' : '../hbs/underscore', 'i18nprecompile' : '../hbs/i18nprecompile', 'json2' : '../hbs/json2'
}
but from directory structure, Hanldebars.js and hbs.js is at the same level as demo.html, so why it is not
paths : { 'hbs' : 'hbs', 'handlebars' : 'Handlebars', ..
Thanks for your help!
@iyip , not sure if you are using older code, but the i18nprecompile.js file should not have an uppercase 'H' in the define. So it should be:
define(['handlebars', "underscore"], function ( Handlebars, _ ) {
then remove the:
Handlebars: 'lib/Handlebars',
//somehow both Handlebars and handlebars are needed
lines from your require config.
Finally, you don't have the directories required for i18n so hbs will fail if you don't add:
hbs : {
disableI18n : true
}
to your require config.
So your final require config will look something like this:
require.config({
baseUrl: "./static/js/",
hbs : {
disableI18n : true
},
paths: {
jquery: 'lib/jquery-1.8.3.min',
underscore: 'lib/underscore-1.4.3.min',
backbone: 'lib/backbone-0.9.2.min',
'backbone.ModelBinder': 'lib/Backbone.ModelBinder-0.1.5.min',
'backbone.deepmodel' : 'lib/deep-model',
text: 'lib/text-2.0.3',
handlebars : "lib/Handlebars",
hbs : 'lib/hbs',
i18nprecompile : "lib/hbs/i18nprecompile",
json2 : "lib/hbs/json2",
bootstrap : 'lib/bootstrap'
},
shim: {
underscore: {
exports: "_"
},
bootstrap: {
deps: ['jquery']
},
backbone: {
deps: ['underscore', 'jquery'],
exports: 'Backbone'
},
'backbone.ModelBinder': {
deps: ['backbone'],
exports: 'Backbone.ModelBinder'
},
'backbone.deepmodel': {
deps: ['backbone'],
exports: 'Backbone.DeepModel'
}
}
});
I made these changes with the sample project you posted and it works fine.
I'm having the same problem:
Uncaught Error: Load timeout for modules: hbs!templates/header_unnormalized6,hbs!templates/menu_unnormalized7, ....etc.
Any ideas what's going wrong?
i have the same problem
This was happening to me because I had been loading handlebars both through direct path 'vendor/handlebars' and through prefix defined in requirejs paths: 'Handlebars'. To fix the issue you should always load handlebars by same name. require-handlebars-plugin uses 'Handlebars' internally so you can either patch require-handlebars-plugin if you want to stick to your existing naming scheme or use 'Handlebars' throughout the whole application.
@ceej86 how do you get the most up to date code of i18nprecompile.js ?
I'm having this same timeout problem as well.
Hi all, I had the same issue which I resolved the same way as drola and ceej86. I removed the capital letters from handlebars on two places:
in hbs.js
"define(['hbs','handlebars'"+depStr+helpDepStr+"] instead of "define(['hbs','Handlebars'"+depStr+helpDepStr+"]
and
in i18nprecompile.js
define(['handlebars', "underscore"], function ( Handlebars, _ ) { instead of define(['Handlebars', "underscore"], function ( Handlebars, _ ) {
then my main has paths like so (lib is sibling to js directory, not within it):
handlebars : "../lib/hbs/handlebars",
hbs: '../lib/hbs/hbs',
i18nprecompile : "../lib/hbs/i18nprecompile",
json2 : "../lib/hbs/json2"
HI, I also had a similar issue for version 0.8.1. My requirejs.config looks like this:
paths: {
jquery: 'libs/jquery/dist/jquery',
underscore: 'libs/underscore/underscore',
backbone: 'libs/backbone/backbone',
bootstrap: '/css/vendor/bootstrap/dist/js/bootstrap',
jqueryui: 'libs/jquery-ui/jquery-ui',
hbs: 'libs/require-handlebars-plugin/hbs',
handlebars: 'libs/require-handlebars-plugin/hbs/handlebars',
},
But it was trying to load handlebars twice using the one defined above and that within hbs.js hbs/handlebars. To fix this, I could either do one of two things 1) change hbs.js to be define(['handlebars'..]) instead of define(['hbs/handlebar'..]) OR 2) I did this instead in my requirejs:
map: {
'*': {
'hbs/underscore': 'underscore',
'hbs/handlebars': 'handlebars'
}
}
Now the hbs/handlebars maps to the original handlebars, and it doesn't try to load it twice.