How to use Backbone.Marionette.ItemView with Mustache
Asked Answered
C

2

8

The following code works fine using Backbone.Marionette.ItemView but not Mustache.

Backbone.Marionette.ItemView - no Mustache

I would like to use the same code but loading the template varaible using Mustache.

Here is my code:

Backbone.Marionette.ItemView - with Mustache

Any idea why my code does not work and why?

Thanks

Chilblain answered 18/6, 2012 at 13:33 Comment(0)
E
8

Marionette assumes the use of UnderscoreJS templates by default. Simply replacing the template configuration for a view isn't enough. You also need to replace how the rendering process works.

In your simple example, you only need to override the Marionette.Renderer.render function to call Mustache, and then set the template of your views to the string template that you want:


Backbone.Marionette.Renderer.render = function(template, data){
  return Mustache.to_html(template, data);
}

var rowTemplate = '{{ username }}{{ fullname }}';

// A Grid Row
var GridRow = Backbone.Marionette.ItemView.extend({
    template: rowTemplate,
    tagName: "tr"
});

Note that your JSFiddle still won't work even when you put this code in place, because the GridView is still using a jQuery selector/string as the template attribute. You'll need to replace this with the same type of template function to return mustache.

http://jsfiddle.net/derickbailey/d7qDz/

Ezaria answered 18/6, 2012 at 15:37 Comment(3)
Looking at the source (derickbailey.github.com/backbone.marionette/docs/…) it seems to me that it should be enough to override Backbone.Marionette.TemplateCache.prototype.compileTemplate: jsfiddle.net/me4NK/78 What is more appropriate way?Thorlie
it depends on whether or not you are using the default behavior of selecting a template from the DOM, or providing the template as a raw string. In the case of this question, the template is a raw string, so overriding Renderer.render is more appropriate. If the template is a DOM <script> tag, though, then the TemplateCache compileTemplate function would be the correct choice.Ezaria
Which is better to use with iCanHaz which holds it templates in index.html? Please help if you can, here's more detail -- #15640668Eyecatching
E
14

I'd like to update the answer here a bit as I was just struggling with this, and I was using this answer as a reference.

Here are my findings:

The answer here is a bit out of date with the current version of Mustache (which is understandable as it's pretty old)

  • Mustache.to_html is now deprecated, but still exists as a simple wrapper around Mustache.render for backwards compat. Check out this link.

Additionally, I found overriding Marionette.Renderer.render, as in the accepted answer above, completely bypasses the Marionette.TemplateCache layer which may not be the desired behavior.

Here's the source for the Marionette.Renderer.render method:

render: function(template, data){

  if (!template) {
    var error = new Error("Cannot render the template since it's false, null or undefined.");
    error.name = "TemplateNotFoundError";
    throw error;
  }

  var templateFunc;
  if (typeof template === "function"){
    templateFunc = template;
  } else {
    templateFunc = Marionette.TemplateCache.get(template);
  }

  return templateFunc(data);
}

Source

As you can see it accesses the Marionette.TemplateCache.get method and the above answer does nothing to maintain that functionality.

Now to get to my solve (note: the above answer is not wrong necessarily; this is just my approach to maintain the Marionette.TemplateCache layer):

As the comments suggest above, override compileTemplate instead:

Marionette.TemplateCache.prototype.compileTemplate = function(rawTemplate) {

    // Mustache.parse will not return anything useful (returns an array)
    // The render function from Marionette.Renderer.render expects a function
    // so instead pass a partial of Mustache.render 
    // with rawTemplate as the initial parameter.

    // Additionally Mustache.compile no longer exists so we must use parse.
    Mustache.parse(rawTemplate);
    return _.partial(Mustache.render, rawTemplate);
};

Here's a working JSFiddle as proof.

In the fiddle, I've also overridden Marionette.TemplateCache.loadTemplate to demonstrate that it's only called once. The body of the function only adds some debug output and then re-implements most of the original functionality (minus error handling).

Ebarta answered 9/2, 2014 at 23:26 Comment(0)
E
8

Marionette assumes the use of UnderscoreJS templates by default. Simply replacing the template configuration for a view isn't enough. You also need to replace how the rendering process works.

In your simple example, you only need to override the Marionette.Renderer.render function to call Mustache, and then set the template of your views to the string template that you want:


Backbone.Marionette.Renderer.render = function(template, data){
  return Mustache.to_html(template, data);
}

var rowTemplate = '{{ username }}{{ fullname }}';

// A Grid Row
var GridRow = Backbone.Marionette.ItemView.extend({
    template: rowTemplate,
    tagName: "tr"
});

Note that your JSFiddle still won't work even when you put this code in place, because the GridView is still using a jQuery selector/string as the template attribute. You'll need to replace this with the same type of template function to return mustache.

http://jsfiddle.net/derickbailey/d7qDz/

Ezaria answered 18/6, 2012 at 15:37 Comment(3)
Looking at the source (derickbailey.github.com/backbone.marionette/docs/…) it seems to me that it should be enough to override Backbone.Marionette.TemplateCache.prototype.compileTemplate: jsfiddle.net/me4NK/78 What is more appropriate way?Thorlie
it depends on whether or not you are using the default behavior of selecting a template from the DOM, or providing the template as a raw string. In the case of this question, the template is a raw string, so overriding Renderer.render is more appropriate. If the template is a DOM <script> tag, though, then the TemplateCache compileTemplate function would be the correct choice.Ezaria
Which is better to use with iCanHaz which holds it templates in index.html? Please help if you can, here's more detail -- #15640668Eyecatching

© 2022 - 2024 — McMap. All rights reserved.