require-handlebars-plugin icon indicating copy to clipboard operation
require-handlebars-plugin copied to clipboard

Problem with loading handlebar template with require js

Open iyip opened this issue 12 years ago • 16 comments

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.

iyip avatar Jan 05 '13 00:01 iyip

Missed one line: In my index.html I have:

could this issue be related to issue #73 ?

iyip avatar Jan 05 '13 00:01 iyip

my index.html just says look at static/js/main.js

iyip avatar Jan 05 '13 00:01 iyip

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.

SlexAxton avatar Jan 05 '13 00:01 SlexAxton

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!

iyip avatar Jan 05 '13 05:01 iyip

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/

iyip avatar Jan 05 '13 19:01 iyip

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.

SlexAxton avatar Jan 06 '13 20:01 SlexAxton

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.)

SlexAxton avatar Jan 06 '13 20:01 SlexAxton

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

iyip avatar Jan 07 '13 05:01 iyip

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 avatar Jan 07 '13 15:01 iyip

@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.

ceejtron avatar Jan 18 '13 03:01 ceejtron

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?

nassdonald avatar Feb 26 '13 12:02 nassdonald

i have the same problem

kazkovsky avatar Apr 17 '13 14:04 kazkovsky

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.

drola avatar Apr 20 '13 11:04 drola

@ceej86 how do you get the most up to date code of i18nprecompile.js ?

I'm having this same timeout problem as well.

quangv avatar May 10 '13 17:05 quangv

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"

andreypetrov avatar Sep 13 '13 12:09 andreypetrov

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.

decoursin avatar Sep 11 '14 14:09 decoursin