Forward Advance Learning

Templates

Packing your render methods full of jQuery rapidly becomes yawnsome. Templates are a way of helping you to write less HTML generation code by compiling strings.

Backbone does not come with a templating language of it's own, but is designed to work well with underscore templates.

Generating a template

We can generate a template by passing a string to the _.template function. This will return a function which we can call to generate an HTML string, like so:

var template = _.template("<p>Hello!</p>");
template();
// outputs "<p>Hello!</p>"

Let's use our template to generate a view:

$(function () {
var template = _.template("<p>Hello World!</p>");
var SharkTankView = Backbone.View.extend({
initialize: function () {
this.render();
},
render: function () {
this.$el.html(template);
}
});
new SharkTankView({
el: $('#tank'),
});
});

Note that we don't need to call the template. If this.$el.html receives a function instead of a string, it will call the function for us.

Template includes

We can include variables in our templates using erb style syntax. We can then generate a string by calling the template function and passing an object, like so:

var template = _.template("<p>Hello <%= name %>!</p>");
template({name: "Wavy Davey"})
// generates the string "<p>Hello Wavy Davey!</p>"

You need to make sure you pass through all attributes or you will get an error.

Extracting Templates from your HTML

Creating templates as strings in JavaScript is OK, provided our templates are very small, but what if they become larger? It would be much nicer if we could define templates directly in our HTML, and of course we can.

We compose the template into our HTML page, then we just use jQuery to pull it out as a string which we can then pass to _.template.

The convention is to put the template in a script tag with type="text/template". Content between script tags will not be rendered to the page, but can still be accessed using jQuery.

See below:

<!DOCTYPE html>
<html>
<head>
<title>Hello</title>
<script src="../../underscore.js"></script>
<script src="../../jquery.js"></script>
<script src="../../backbone.js"></script>
<script src="hello.js"></script>
</head>
<body>
<div id="tank"></div>
<!-- And here is the template -->
<script type="text/template" id="tank-template">
<p>Swim Away <%= name %></p>
</script>
</body>
</html>

We then pull this content as a string using a simple jQuery selector, and store it as a template function in the tankTemplate attribute.

Then in our render function we can simply call the template, passing in any expected values.

var SharkTankView = Backbone.View.extend({
initialize: function () {
this.render();
},
tankTemplate: _.template(
$('#tank-template').html()
),
render: function () {
this.$el.html(this.tankTemplate({
name: "Danger Mouse McGree"
}));
}
});

Executing code in our templates

We can execute arbitrary code in our templates. They become, in many ways, rather like PHP templates. For example, say we have an array, we might use a regular forEach function to iterate over it:

<script type="text/template" id="hello-template">
<ul>
<% names.forEach((name) => { %>
<li>
<%= name %>
</li>
<% }) %>
</ul>
</script>

Exercise - Templates

Angular uses Underscore templates by default. Underscore templates are brilliantly simple. Pass them a string, and you will get a function back. Call the function with an object and you will get a string back with the values from the template embedded in it.

Create a Hello World using a template.

Exercise - A Cat

Let's make a little object to represent a cat, something like this:

{
name: 'Tiddles the Mighty',
age: 47
}

Now create a template that can render this cat nicely on the page.

Extension

Make that an array of cats. Now output them all as a list.

Further reading

Have a look through the underscore template documentation here. It's pretty short:

http://underscorejs.org/#template