Rendering templates is a piece of cake when the data displayed within the template is either internationalized text OR model attributes, but when it comes to rendering BOTH within one template, I can’t seem to find a clean solution.
For reference, I’m utilizing i18n via Require.js’s i18n plugin.
Let’s assume I have a simple template:
<h3>{{displayText.load}} #{{id}}</h3>
<h4 id="loading-load-data">{{displayText.loadingLoadData}}...</h4>
The displayText object represents i18n text, while the id item represents a Backbone Model attribute.
Using Backbone’s template property on a View, I can do the following in order to render a template with i18n text, but without Model attribute data:
return Backbone.Marionette.ItemView.extend({
template: function () {
var compiledTemplate = Handlebars.compileClean(template);
// localizedText represents the i18n localization object, using the Require.js i18n plugin
return compiledTemplate(localizedText);
},
// some more View properties and methods
});
However, once I want to also display the Model data, this no longer works, primarily due to this being undefined within the template attribute (so I can’t reference this.model.attributes), and it seems that I have to fall back to overriding the render() method, passing both the i18n object AND Model attributes to the template, as such:
return Backbone.Marionette.ItemView.extend({
template: Handlebars.compileClean(template),
render: function() {
var templateParams = _.extend({}, this.model.attributes, localizedText),
renderedTemplate = this.template(templateParams);
this.$el.html(renderedTemplate);
this.bindUIElements();
this.delegateEvents();
return this;
}
});
I’d really love to leave Marionette’s default handling of render() in place, and solely use the template property to render both i18n text AND the Model data. Is this possible?
BONUS: Assuming I DO have to override render(), I’m noticing that while doing so, the this.ui attribute, provided on Marionette Views, no longer wraps each item as a jQuery object. This means that:
this.ui.loadingNotification.show();
stops functioning, throwing an Uncaught TypeError: Object #loading-load-data has no method 'show'. Why is this, and how can I restore proper this.ui jQuery-wrapping functionality?
EDIT: Solved the BONUS; simply have to toss in a this.bindUIElements() call within the render() method to properly bind the elements to the ui hash. See the render() example above.
SOLVED: So the answer is embarrassingly simple. Turns out you can pass a parameter into the template: property when used as a function, and this parameter represents the Model associated with that View/template:
The
render()method then no longer needs to be overwritten, and both i18n text and Model data can be rendered into the template as expected.