0
votes

What I want to do is to configure Marionette to load external Handlebars template files instead of doing <script id="templateId" type="text/template">...</script>.

I stumbled upon @Derick Bailey's post at External handlebars templates backbone marionette ... but apparently, it doesn't work for me as I'm getting the same "callback is undefined", as pointed out by one of the comments. I'm using Marionette 2.2.0... by the way.

This is what I have come out with:-

Backbone.Marionette.Renderer.render = function ( templateId, data ) {
    console.log( "render() - " + templateId + " " + JSON.stringify( data, null, 4 ) );

    var promise = Backbone.Marionette.TemplateCache.get( templateId );

    $.when( promise ).done( function ( template ) {
        console.log( "render() - promise fulfilled - " + template );
        return template( data );
    } );
};

Backbone.Marionette.TemplateCache.prototype.loadTemplate = function ( templateId ) {
    console.log( "loadTemplate() - " + templateId );
    var tmpId = templateId.replace( "#", "" ),
        url = "resources/js/templates/" + tmpId + ".html";

    var renderer = $.Deferred();
    $.get( url, function ( templateHtml ) {
        console.log( "loadTemplate() - URL get - " + templateHtml );
        renderer.resolve( Handlebars.compile( templateHtml ) );
    } );

    return renderer.promise();
};

While, I'm not getting any errors, I'm also not seeing any rendered template on the screen.

Looking at the Firebug console, I'm seeing the following....

enter image description here

How do I fix it? I have spent several hours trying to solve this, but I'm getting frustrated now.

Thanks much.

2

2 Answers

0
votes

Main issue in your implementation is in declaration of Backbone.Marionette.Renderer.render.

When you calling Backbone.Marionette.TemplateCache.get( templateId ) in order to receive promise object back, Backbone.Marionette.TemplateCache.get( templateId ) calls Backbone.Marionette.TemplateCache.load.

load: function() {
    // Guard clause to prevent loading this template more than once
    if (this.compiledTemplate) {
      return this.compiledTemplate;
    }

    // Load the template and compile it
    var template = this.loadTemplate(this.templateId);
    this.compiledTemplate = this.compileTemplate(template);

    return this.compiledTemplate;
}

From definition of load function you can see that it will return not a promise as you expected but it will call compileTemplate(template) and will return result of it.

As I can see from you source code you did't change this.compileTemplate(); method and it's still using underscores template function.

To solve your task just fix that issue and try again or use almost the same approach suggested here.

0
votes

I have figured out the solution of this problem:-

Backbone.Marionette.TemplateCache.prototype.loadTemplate = function ( templateId ) {
    var template = '',
        url = 'resources/js/templates/' + templateId + '.html';

    // Load the template by fetching the URL content synchronously.
    Backbone.$.ajax( {
        async   : false,
        url     : url,
        success : function ( templateHtml ) {
            template = templateHtml;
        }
    } );

    return template;
};

// Instruct Marionette to use Handlebars.
Marionette.TemplateCache.prototype.compileTemplate = function ( template ) {
    return Handlebars.compile( template );
};

If you want to load external Underscore template files instead, then you can safely omit Marionette.TemplateCache.prototype.compileTemplate so that Marionette will use Underscore template, which is the default.