JavaScript Mustache tutorial

In JavaScript Mustache tutorial, we show how to use Mustache template engine.

Mustache is a simple web template system. It is available for many programming languages including JavaScript and Java. Mustache is described as a logic-less template engine because it does not have any explicit control flow statements, such as if and else conditionals or for loops. Looping and conditional evaluation can be achieved using section tags processing lists and lambdas.

JSON (JavaScript Object Notation) is a lightweight data-interchange format. It is easy for humans to read and write and for machines to parse and generate. The application/json is the official Internet media type for JSON. The JSON filename extension is .json.

jQuery is a JavaScript library which is used to manipulate DOM. With jQuery, we can find, select, traverse, and manipulate parts of a HTML document.

<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>

Mustache is a JavaScript library, which can be referenced from a CDN (Content Delivery Network).

Basic template example

In the first example, we have a basic template example.

basic.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Mustache template</title>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>

</head>

<body>

<div id="mypanel"></div>

<button id="btn">Load</button>

<script>
$("#btn").on('click', function() {

    var data = { name: "Jonathan" };
    var template = "Hello {{ name }}";
    
    var text = Mustache.render(template, data);        

    $("#mypanel").html(text);
});
</script>

</body>
</html>

Clicking on the button we get a message written on the page.

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>

In the example, we use JQuery and Mustache JavaScript libraries.

$("#btn").on('click', function() {
...
}

We create a handler that reacts to the button click event.

var data = { name: "Jonathan" };

This is the data.

var template = "Hello {{ name }}";

This is the Mustache template. The {{ name }} is a Mustache tag which is replaced with the data value.

var text = Mustache.render(template, data); 

The final output is rendered with the Mustache.render() function. A template engine joins template with data to generate output.

$("#mypanel").html(text);

The rendered text is written to the panel element.

Using template tag

In the second example, we use a template tag. Currently the <script type="text/template"> is used but it is going to be replaced with <template> tag in the near future. The tag holds client-side content that is not to be rendered when a page is loaded but is instantiated during runtime using JavaScript.

json_url.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>JavaScript Mustache template</title>

<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">

<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>

</head>

<body>

<script id="mp_template" type="text/template">
    Date: {{ time }} 
    <br> 
    Time: {{ date }} 
    <br> 
    Unix time: {{ milliseconds_since_epoch }}
</script>

<div id="mypanel"></div>

<button id="btn">Load</button>

<script>

    $(function() { 

        $("#btn").on('click', function() {

            $.getJSON('http://time.jsontest.com', function(data) {
            
                    var template = $("#mp_template").html();
                    var text = Mustache.render(template, data);
        
                    $("#mypanel").html(text);
            });
        });
    }); 
</script>

In this example, we make a request to time.jsontest.com, which returns a JSON response with three attributes: time, date, and milliseconds_since_epoch (Unix time).

<script id="mp_template" type="text/template">
    Date: {{ time }} 
    <br> 
    Time: {{ date }} 
    <br> 
    Unix time: {{ milliseconds_since_epoch }}
</script>

We define the template inside the <script id="mp_template" type="text/template"> tag.

$.getJSON('http://time.jsontest.com', function(data) {

With $.getJSON(), we load JSON-encoded data from a server using a GET HTTP request.

var template = $("#mp_template").html();

With JQuery's html() method, we get the template data.

var text = Mustache.render(template, data);      

The output is rendered with Mustache.render().

$("#mypanel").html(text);

The final text is written to the panel element.

Mustache with Java Servlet

In the third example, we create a Java web application with a servlet.

$ tree
.
├── pom.xml
└── src
    ├── main
    │   ├── java
    │   │   └── com
    │   │       └── zetcode
    │   │           ├── bean
    │   │           │   └── City.java
    │   │           └── web
    │   │               └── GetCities.java
    │   └── webapp
    │       ├── index.html
    │       ├── META-INF
    │       │   └── context.xml
    │       └── WEB-INF
    └── test
        └── java

This is the project structure.

pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" 
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd">
    
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.zetcode</groupId>
    <artifactId>ServletJsonMustache</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>war</packaging>

    <name>ServletJsonMustache</name>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    
    <dependencies>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>javax.servlet-api</artifactId>
            <version>3.1.0</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>com.google.code.gson</groupId>
            <artifactId>gson</artifactId>
            <version>2.8.0</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-war-plugin</artifactId>
                <version>2.3</version>
                <configuration>
                    <failOnMissingWebXml>false</failOnMissingWebXml>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>

This is the Maven POM file. We have two artifacts: javax.servlet-api for servlets and gson for JSON processing in Java.

context.xml
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ServletJsonMustache"/>

In the Tomcat context.xml file, we define the context path. It is the name of the web application.

City.java
package com.zetcode.bean;

public class City {

    private Long id;
    private String name;
    private int population;

    public City() {
    }

    public City(Long id, String name, int population) {
        this.id = id;
        this.name = name;
        this.population = population;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getPopulation() {
        return population;
    }

    public void setPopulation(int population) {
        this.population = population;
    }

    @Override
    public String toString() {
        return "City{" + "id=" + id + ", name=" + name + 
                ", population=" + population + '}';
    }
}

This is the City bean. It has three attributes: id, name, and population.

GetCities.java
package com.zetcode.web;

import com.google.gson.Gson;
import com.zetcode.bean.City;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@WebServlet(name = "GetCities", urlPatterns = {"/GetCities"})
public class GetCities extends HttpServlet {
    
    private static final List<City> cities;
    
    static {
        
        cities = new ArrayList<>();
        cities.add(new City(1L, "Bratislava", 432000));
        cities.add(new City(2L, "Budapest", 1759000));
        cities.add(new City(3L, "Prague", 1280000));
        cities.add(new City(4L, "Warsaw", 1748000));
        cities.add(new City(5L, "Los Angeles", 3971000));
        cities.add(new City(6L, "New York", 8550000));
        cities.add(new City(7L, "Edinburgh", 464000));
        cities.add(new City(8L, "Berlin", 3671000));
    }

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
        
        response.setContentType("application/json;charset=UTF-8");

        try (ServletOutputStream os = response.getOutputStream()) {
            os.print(new Gson().toJson(cities));
        }
    }
}

This is the GetCities servlet.

response.setContentType("application/json;charset=UTF-8");

The content type of the response object is set to application/json.

try (ServletOutputStream os = response.getOutputStream()) {
    os.print(new Gson().toJson(cities));
}

We use the Gson library to transform a Java list into JSON array. The array is written to the response output stream. The array was not not given a name.

index.html
<!DOCTYPE html>
<html>
    <head>
        <title>Cities</title>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
        <script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/2.3.0/mustache.min.js"></script>
    </head>
    <body>
        <script id="mp_template" type="text/template">
            <table>
                <thead>
                    <tr>
                        <th>Id</th>
                        <th>Name</th>
                        <th>Price</th>
                    </tr>
                </thead>
                
                <tbody>
                {{#.}}
                    <tr>
                        <td>{{id}}</td>
                        <td>{{name}}</td>
                        <td>{{population}}</td>
                    </tr>
                {{/.}}    
                </tbody>
            </table>
        </script>

        <div id="mypanel"></div>

        <button id="btn">Load</button>

        <script>

            $(function () {

                $("#btn").on('click', function () {

                    $.getJSON('http://localhost:8084/ServletJsonMustache/GetCities', function (cities) {

                        var template = $("#mp_template").html();
                        var text = Mustache.render(template, cities);
                        
                        $("#mypanel").html(text);
                    });
                });
            });
        </script>
    </body>
</html>

This is the home page.

<script id="mp_template" type="text/template">
...
</script>

The Mustache template is placed in the <script id="mp_template" type="text/template"> tag.

<tbody>
{{#.}}
    <tr>
        <td>{{id}}</td>
        <td>{{name}}</td>
        <td>{{population}}</td>
    </tr>
{{/.}}    
</tbody>

With {{#.}} {{/.}} syntax we go through the unnamed JSON array returned from the servlet and replace Mustache tags with values.

$.getJSON('http://localhost:8084/ServletJsonMustache/GetCities', function (cities) {

With $.getJSON() we call the GetCities servlet. The servlet returns JSON data, which are processed with Mustache.

Naming the JSON array

In case we wanted to name the returned JSON array, we can use the following code:

Gson gson = new GsonBuilder().create();
JsonArray jarray = gson.toJsonTree(cities).getAsJsonArray();
JsonObject jsonObject = new JsonObject();
jsonObject.add("cities", jarray);

os.print(jsonObject.toString());

In the servlet, we place the JSON array into another JSON object and name the property cities.

<tbody>
{{#cities}}
    <tr>
        <td>{{id}}</td>
        <td>{{name}}</td>
        <td>{{population}}</td>
    </tr>
{{/cities}}    
</tbody>

In the Mustache template, we use this syntax: {{#cities}} {{/cities}}.

Rendering JSON data from Servlet with Mustache
Figure: Rendering JSON data from Servlet with Mustache

In this tutorial, we have worked with the Mustache template engine.

You might also be interested in the following related tutorials: Reading JSON from URL in JavaScript, JQuery tutorial, jQuery Autocomplete tutorial, or Using jQuery DatePicker.