Tutorial: HTML Templates with Mustache.js

}

When developing modern HTML applications, you often write a lot of HTML fragments programmatically. You concatenate HTML tags and dynamic data, and insert the resulting UI markup into the DOM. Here is a random code example of this approach:

$.each(messages.reverse(), function(index, message) {
	$('#messageList').append(
		'<li><span class="list-title">' +
		message.userName + '</span>' +
		'<abbr class="list-timestamp" title="' +
		message.datePosted + '"></abbr>' +
		'<p class="list-text">' + message.messageText + '</p></li>');
	}
});

The proliferation of this kind of code throughout your application comes with some downsides. The tight coupling of UI and data logic doesn’t promote separation of concerns and reuse. It makes your application harder to write and harder to maintain.

HTML templates address this issue by decoupling the UI definition (HTML markup) from the data. There are a number of HTML template solutions out there: jQuery Templates, Underscore.js, and Mustache.js to name a few. Mustache.js is a popular choice because of its powerful syntax and fast rendering.

Mustache is a “logic-less” template syntax. “Logic-less” means that it doesn’t rely on procedural statements (if, else, for, etc.): Mustache templates are entirely defined with tags. Mustache is implemented in different languages: Ruby, JavaScript, Python, PHP, Perl, Objective-C, Java, .NET, Android, C++, Go, Lua, Scala, etc. Mustache.js is the JavaScript implementation.

In this article, we take a quick tour of some of the capabilities of Mustache.js.

To start using Mustache.js, simply add a script tag to your html file pointing to mustache.js which is available here.

You can run all the examples below here.

Sample 1: Basic Template

This is a self-explanatory example. Note that:

  • Instead of being defined in a variable, the data often comes from a service call (see sample 2)
  • Instead of being defined in a variable, the template is often read from a file (see sample 3)
	var person = {
		firstName: "Christophe",
		lastName: "Coenraets",
		blogURL: "http://coenraets.org"
	};
	var template = "<h1>{{firstName}} {{lastName}}</h1>Blog: {{blogURL}}";
	var html = Mustache.to_html(template, person);
	$('#sampleArea').html(html);

Result:

Christophe Coenraets

Blog: http://coenraets.org

 

Sample 2: Basic Template using Ajax data

Same as sample 1, except that we get the data from an Ajax service call.

$.getJSON('json/data.json', function(data) {
	var template = "<h1>{{firstName}} {{lastName}}</h1>Blog: {{blogURL}}";
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});

Result:

John Smith

Blog: http://johnsmith.com

 

Sample 3: Externalized Template

Same as sample 2, except that we read the template from the main HTML file.

$.getJSON('json/data2.json', function(data) {
	var template = $('#personTpl').html();
	var html = Mustache.to_html(template, data);
	$('#sampleArea').html(html);
});

The template is defined as follows in index.html:

<script id="personTpl" type="text/template">
<h1>{{firstName}} {{lastName}}</h1>
<p>Blog URL: <a href="{{blogURL}}">{{blogURL}}</a></p>
</script>

Result:

Lisa Jones

Blog URL: http://lisajones.com

 

NOTE: Sample 3 represents the way templates are being used in many dynamic Web applications:

  • You get data from an Ajax service
  • You read the template from an external file

In the remaining of this article, we declare the data and the template in variables to keep the examples self-contained. Remember to refer to sample 3 for a traditional setup when using templates in a dynamic Web application.

 

Sample 4: Enumerable Section

var data = {name: "John Smith", skills: ['JavaScript', 'PHP', 'Java']};
var tpl = "{{name}} skills:<ul>{{#skills}}<li>{{.}}</li>{{/skills}}</ul>";
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);

Result:

John Smith skills:
  • JavaScript
  • PHP
  • Java

 

Sample 5: Enumerable Section with Objects

var data = {
	employees: [
	{	firstName: "Christophe",
		lastName: "Coenraets"},
	{	firstName: "John",
		lastName: "Smith"}
	]};
var template = "Employees:<ul>{{#employees}}" +
                            "<li>{{firstName}} {{lastName}}</li>" +
                            "{{/employees}}</ul>";
var html = Mustache.to_html(template, data);
$('#sampleArea').html(html);

Result:

Employees:
  • Christophe Coenraets
  • John Smith

 

Sample 6: Nested Objects

You can use the dot notation to access object properties.

var person = {
	firstName: "Christophe",
	lastName: "Coenraets",
	blogURL: "http://coenraets.org",
	manager : {
		firstName: "John",
		lastName: "Smith"
	}
};
var template = "<h1>{{firstName}} {{lastName}}</h1><p>{{blogURL}}</p>" +
               "Manager: {{manager.firstName}} {{manager.lastName}}";
var html = Mustache.to_html(template, person);
$('#sampleArea').html(html);

Result:

Christophe Coenraets

http://coenraets.org

Manager: John Smith

 

Sample 7: Dereferencing

Same as sample 6, except that we “dereference” the manager object to make it easier to access its properties (without having to use the dot notation).

var person = {
	firstName: "John",
	lastName: "Smith",
	blogURL: "http://johnsmith.com",
	manager : {
		firstName: "Lisa",
		lastName: "Jones"
	}
};
var tpl = "<h1>{{firstName}} {{lastName}}</h1><p>{{blogURL}}</p>" +
          "{{#manager}}Manager: {{firstName}} {{lastName}}{{/manager}}";
var html = Mustache.to_html(tpl, person);
$('#sampleArea').html(html);

Result:

John Smith

http://johnsmith.com

Manager: Lisa Jones

 

Sample 8: Function

Templates can reference functions like totalPrice in this example.

var product = {
	name: "FooBar",
	price: 100,
	salesTax: 0.05,
	totalPrice: function() {
		return this.price + this.price * this.salesTax;
	}
};
var template = "<p>Product Name: {{name}}</p>Price: {{totalPrice}}";
var html = Mustache.to_html(template, product);
$('#sampleArea').html(html);

Result:

Product Name: FooBar

Price: 105

 

Sample 9: Condition

Templates can include conditional sections. Conditional sections only render if the condition evaluates to true. A conditional section begins with {{#condition}} and ends with {{/condition}}. “condition” can be a boolean value or a function returning a boolean.

var data = {
	employees: [
	{	firstName: "Christophe",
		lastName: "Coenraets",
		fullTime: true,
		phone: "617-123-4567"
	},
	{	firstName: "John",
		lastName: "Smith",
		fullTime: false,
		phone: "617-987-6543"
	},
	{	firstName: "Lisa",
		lastName: "Jones",
		fullTime: true,
		phone: "617-111-2323"
	},
	]};
var tpl = "Employees:<ul>{{#employees}}<li>{{firstName}} {{lastName}}" +
          "{{#fullTime}} {{phone}}{{/fullTime}}</li>{{/employees}}</ul>";
var html = Mustache.to_html(tpl, data);
$('#sampleArea').html(html);

Result:

Employees:
  • Christophe Coenraets 617-123-4567
  • John Smith
  • Lisa Jones 617-111-2323

 

Sample 10: Partials

var data = {
	firstName: "Christophe",
	lastName: "Coenraets",
	address: "1 Main street",
	city: "Boston",
	state: "MA",
	zip: "02106"
};

var template = "<h1>{{firstName}} {{lastName}}</h1>{{>address}}";
var partials = {address: "<p>{{address}}</p>{{city}}, {{state}} {{zip}}"};
var html = Mustache.to_html(template, data, partials);
$('#sampleArea').html(html);

Result:

Christophe Coenraets

1 Main street

Boston, MA 02106

 

Sample 11: Partials in Enumerable Section

var data = { depts: [
	{	name: "Engineering",
		employees: [
			{firstName: "Christophe", lastName: "Coenraets"},
			{firstName: "John", lastName: "Smith"}]
	},
	{	name: "Sales",
		employees: [
			{firstName: "Paula", lastName: "Taylor"},
			{firstName: "Lisa", lastName: "Jones"}]
	}]
};

var tpl = "{{#depts}}<h1>{{name}}</h1>" +
          "<ul>{{#employees}}{{>employee}}{{/employees}}</ul>{{/depts}}";
var partials = {employee: "<li>{{firstName}} {{lastName}}</li>"};
var html = Mustache.to_html(tpl, data, partials);
$('#sampleArea').html(html);

Result:

Engineering

  • Christophe Coenraets
  • John Smith

Sales

  • Paula Taylor
  • Lisa Jones

 

You can run all the examples here.

 

css.php