I use Backbone.js a lot lately, and since Backbone requires Underscore.js, I usually end up using Underscore’s templates rather than introducing another Javascript library dependency like Mustache templates. But Underscore’s micro-templating language has an omission that bothered me today: templates can’t include each other.
So here’s a quick and dirty <% include %> tag for Underscore templates:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
// Extend underscore's template() to allow inclusions
function template(str, data) {
// match "<% include template-id %>"
return _.template(
str.replace(
/<%\s*include\s*(.*?)\s*%>/g,
function(match, templateId) {
var el = document.getElementById(templateId);
return el ? el.innerHTML : '';
}
),
data
);
} |
As you can see, the code simply replaces tags like
|
1 |
<% include foo %> |
with the contents of the element with id “foo”. Use it by throwing code like this into the body of your HTML page:
|
1 2 3 4 5 6 7 8 |
<script type="text/template" id="base-template">
Here's a number: <%= n %>
</script>
<script type="text/template" id="imaginary-template">
<% include base-template %> + <%= imaginary %>i
</script> |
And in your Javascript code, do this:
|
1 2 3 4 5 6 7 8 9 10 11 12 |
// Outputs "Here's a number: 17"
function showSimpleNumber() {
var t = template($('#base-template').html());
$('body').html(t({ n: 17 }));
}
// Outputs "Here's a number: 17 + 42i"
function showComplexNumber() {
var t = template($('#imaginary-template').html());
$('body').html(t({ n: 17, i: 42 }));
} |
Enjoy! I leave as an exercise for the reader:
- Cache included templates so the template() function needn’t keep doing document.getElementById().innerHTML for an often-included template
- Create replaceable blocks in templates
- Pass variables from one template to another
