how can I use external templates with Marionette Backbone - backbone.js

How exactly do I use an external template for my Marionette ItemView?
I read so many 'methods' I can't get any of them working...
JST Method ... I'm not on rails so can't use this
Backbone.Marionette.Renderer.render = (template, data) ->
path = JST["backbone/apps/" + template]
unless path
throw "Template #{template} not found!"
path(data)
RequireJS Method ... I'm not using require js
var tpl = require(inject[this.templateName]);
this.template = _.template(tpl);
What method should I be using?

I use Handlebars for my templating engine and hbs to retrieve the precompiled resource via require.js, that way all I have to do is define the template and set it as the ItemView's template; marionette does the rest.
Here's an example
View - welcome.js
define([
'app',
'jquery',
'backbone',
'marionette',
'hbs!templates/welcome'
],
function(App, $, Backbone, Marionette, template) {
return Backbone.Marionette.ItemView.extend({
template: template,
});
});
Template - welcome.html
<div>
<h1>Hello World</h1>
</div>
If you're not using handlebars, or can't use hbs, then something similar can be done with text.js - https://github.com/requirejs/text

Related

Marionette + i18n in templates

I want to do some basic i18n in my application
I loaded the i18n plugin (from require.js) to my Application and created a directory nls in which i have several files e.g. project.js
I set up the default location in main.js file like
config : {
i18n : {
locale : 'de-de'
}
}
I now want to use the files in my View / Template. Can somebody explain to me how this is done? The templates are setup in one template.js file
My View:
define(['marionette', 'templates', 'i18n!nls/project'], function (marionette, templates, msg) {
return marionette.CompositeView.extend({
template : templates.project
});
});
My template:
<div class="container">
<div class="well">
<h2>Projects</h2>
</div>
</div>
Can someone explain to me how to use the file in my View / Template? Thanks in advance!
EDIT:
I figured out the solution by some try&error. As i am loading the templates via the require.js tpl! plugin i dont need to compile them if i call them by require('tpl!templates/dashboard.tmpl'). I can simply pass the i18n file i loaded by 'i18n!nls/dashboard'. In Marionette the view are rendered by default, so i did this:
define(['marionette', 'templates', 'i18n!nls/dashboard'], function (Marionette, templates, msg) {
return Marionette.CompositeView.extend({
template : function () {
return templates.dashboard(msg);
},
initialize : function() {
}
});
});
The files for the i18n plugin are well explained here:
http://requirejs.org/docs/api.html#i18n
I had to do this step by step, first i missed the root, then i wondered why my german locale did not load, but i simply forgot to set de-de : true in the root file. Now everything is working like a charm
first you load the i18 file via require.js to your view.
I use the handlebars templates in this example.
define([
'marionette',
'handlebars',
'text!modules/tableModule/templates/myTmpl.html',
'i18n!nls/dashboard',
],
function(Marionette, Handlebars, tmpl, locals) { ...
then you compile and load your template with the i18 object.
var template = Handlebars.compile(tmpl);
this.template = template(locals.myVar);
you can go and do complex combinations as well
var template = Handlebars.compile(tmpl);
var data =_.extend(options, {lang:locals});
this.template = template(data);
your nls file will look like this
define({
"root": {
"myVar" : "some text in",
"canBeAnObjectTo": {
"title" : "my title ",
"contact" : "Contact",
}
and your view will be something like this:
<div class="cssClass">
<div class="table-caption pull-left">{{this.myVar}}</div>
</div>
hope that helps

How to wire a Backbone View to a meteor handlebars template?

Looks like Backbone.view, meteor and handlebars have overlap functionality when it comes to manipulating a section of the DOM. I looked at the ToDo app which is suppose to use Backbone, but in reality, they only use the Router.
Backbone views also deal with templates... but they sound so different from meteor templates. Besides, it looks like both backbone & meteor can update the ui on a model update.
ok, I am lost!? Who does what?
Is Backbone really useful for a Meteor App? Can Backbone & Handle bars coexist?
and if they can, in the Meteor context, how to wire a Backbone view to a handlebars template?
EDIT: found the todo-backbone example. it seems to confirm that you can go either:
meteor + backbone + underscore templates
or... meteor + handlebars
meteor+backbone+handlebars doesn't seem like a viable option...
Thank you
It's very easy and no more work than using the Underscore template. Here's an example .html file:
<template name="user_list">
<ul>
{{#each users}}
<li>{{name}}</li>
{{/each}}
</ul>
</template>
And here's an example .js file:
Users = new Meteor.collection("users");
if (Meteor.is_client) {
Template.user_list.users = function() {
return Users.find();
}
window.UserView = Backbone.View.extend({
initialize: function() {
_.bindAll(this, 'render');
},
template: function() {
Meteor.ui.render(function() {
return Template.user_list();
});
},
render: function() {
$(el).empty().append(this.template());
}
});
}
You can then use a Router or another View to manage when you want to display the UserView just like you would in any other Backbone.js app.
The key is to use the Meteor.ui.render or other Meteor.ui method to render the HTML so that it's reactive.

RequireJS loads scripts before the view is initialized

I have a Backbone view as a requirejs module. The problem is that requirejs load the http://localhost/remote/script/here.js before the view is even initialized. Is it because the script isn't inside a requirejs module?
define([
'jquery',
'undescore',
'backbone',
'http://localhost/remote/script/here'
], function($, _, Backbone, Luajs){
var View = Backbone.View.extend({
initialize : function(options) {
},
render : function() {
this.$el.html('<p>my view</p>')
return this;
}
});
return View;
});
The array you have as the first argument to define is the depedencies of your view. So yes it is loaded and parsed before the View.
Also note that unless you use modified versions of backbone and underscore, they ar not AMD compliant. You will need to wrap them with a plugin to load them properly.
you try to define the view Backbone after the load the module.
You can do this, in the define () method of RequireJS. The array of this function contains parameters that defines module dependencies.

AMD Module Loading Error with Mustache using RequireJS

I am following the tuturoial here: http://backbonetutorials.com/organizing-backbone-using-modules/ and all I would like to do is use Mustache instead of underscore.js for my templating engine in a Backbone View. Everything is working as expected until I try to do the replacement of Mustache. Firebug gives me this:
Load timeout for modules: Mustache
My Mustache wrapper (in libs/mustache/mustache-wrap.js) is like so:
define(['libs/mustache/mustache'], function(){
// Tell Require.js that this module returns a reference to Mustache
return Mustache;
});
Here is the code for my Backbone View:
// Protocol Detail View
define([
'jQuery',
'Underscore',
'Backbone',
'Mustache',
'collections/protocols',
'text!templates/protocol/protocoldetail.html'
], function($, _, Backbone, Mustache, protocolCollection, protocolDetailTemplate){
var protocolDetailView = Backbone.View.extend({
el: "#asset-detail",
render: function( pid ){
this.collection = new protocolCollection;
this.collection.fetch();
var p = this.collection.getByCid('c'+pid);
var template = "{{name}}";
htmlr = Mustache.to_html(template, p);
$(this.el).html(htmlr);
//var compiledTemplate = _.template( protocolDetailTemplate, { protocol: protocol });
//$(this.el).html(compiledTemplate);
},
events: {
"submit #asset-owner": "chown"
},
chown: function ( pid ){
console.log("Protocol Detail View chown callback.")
}
});
return new protocolDetailView;
});
My main.js file has the following config:
require.config({
paths: {
jQuery: 'libs/jquery/jquery',
jQueryUI: '//ajax.aspnetcdn.com/ajax/jquery.ui/1.8.17/jquery-ui.min',
jstree: 'libs/jstree/jquery.jstree',
Mustache: 'libs/mustache/mustache-wrap',
Underscore: 'libs/underscore/underscore',
Backbone: 'libs/backbone/backbone'
}
});
In you main.js file where you have all you're requires, make sure to add Mustache to the config, and don't worry about the wrapper and just try loading Mustache directly.
require.config({
'paths': {
"underscore": "libs/underscore",
"backbone": "libs/backbone",
"Mustache": "libs/mustache/mustache"
}
});
That might help...
Also, here are some starter apps to help you out on your require, backbone journey.
https://github.com/jcreamer898/RequireJS-Backbone-Starter
https://github.com/david0178418/BackboneJS-AMD-Boilerplate
https://github.com/addyosmani/backbone-fundamentals
https://github.com/amdjs
Clone the repository from github:
$ git clone https://github.com/janl/mustache.js.git
Then, build the RequireJS specific version of the library:
$ rake requirejs
Use the resulting file 'requirejs.mustache.js' as your mustache library.
Use Twitter's mustache repository!
Here is what worked for me (Ubuntu 12.04):
sudo apt-get install rake ruby-rspec
git clone git://github.com/twitter/mustache.js.git
cd mustache.js/
rake requirejs

BackboneJS + Requirejs: Backbone is null issue

In the router.js. The firebug console alerts Backbone is null there. Why???
app.js
define([
'order!jQuery',
'order!Underscore',
'order!Backbone',
'order!router' // Request router.js
],
function($, _, Backbone, Router){
App = {
initialize: function() {
console.log("app.js initalize");
Router.initialize();
}
};
return App;
});
router.js
define([
'order!Underscore',
'order!Backbone'
],
function(_, Backbone){
var AppRouter = Backbone.Router.extend({
// Console shows Backbone is null here, why?
// I'm sure the config is correct.
routes: {
'*actions': "defaultAction"
},
defaultAction: function(actions){
// We have no matching route, lets just log what the URL was
console.log('No route:', actions);
}
});
var initialize = function(){
console.log("Router initialize");
var app_router = new AppRouter;
Backbone.history.start();
};
return {
initialize: initialize
};
});
Backbone does not support the AMD and it doesn't register as module. When required it registers normally as a global Backbone object, also since 1.3 Underscore doesn't support AMD neither and if you will require Backbone and Underscore under Backbone and _ namespaces they will overwrite its values in this modules scope to undefined cause of that.
jQuery supports AMD but it also registers itself as a global instance. Basically it means that you don't need to require jquery, underscore and backbone multiple times - it's enough if you do it once in your requirejs main script
The alternative is to hack the backbone.js library.
Note: This will allow you to reference Backbone.js and underscore.js library within your require.js defines, but it will not stop them from being added to the global namespace/window object. This requires a little more hacking.
Find:
(function(){var l=this,y=
Replace it with:
define('backbone',['underscore','jquery'],function(_,$){
var l = this;
(function(){var y=
Add this to the bottom of the page:
return l.Backbone;
});
Then do the same for underscore.js
Prefix the beginning with:
define('underscore',function(){
Add to the bottom of the page:
return this._;
});

Resources