How to Render Markup with JavaScript Mustache Template
The Web has grown so much since I first started creating static pages back in 1992, yes I am that old.
Today modern web applications can be rich client experiences that rival native applications. This means they must be quick and dynamic.
We have made several major architectural changes over the 25+ years. The latest trend has been single page applications. But an emerging trend is static sites, where all the markup is pre-rendered on the server before it is requested.
Either way the general work flow is to compose HTML from some combination of HTML template and JSON data.
I have gone through many iterations of this process in my applications. Unless you are using an MVVM engine the process is basically the same. MVVM is a close relative, but has poor performance profiles so I don't use it.
Several years ago I discovered John Resig's Micro-Templating library and it revolutionized the way I built web applications. That library was the forerunner of the jQuery template library and several other libraries.
I used the jQuery Templates library for several years. I presented and wrote about them several times back in the day. However, it ultimately found itself in a perpetual Beta as no one wanted to take project ownership.
As I focused more and more on mobile first development I had to purge jQuery from my core web stack for performance reasons. This meant I needed to find a new JavaScript templating library. There are many rendering solution choices, each with their strengths and weaknesses. I finally settled on using Mustache. It is simple, yet provides enough functionality to cover just about every scenario.
Mustache is framework agnostic, meaning it is not tightly coupled to a particular library, framework or language. The ability to stand-alone is always an important 'feature' when I evaluate potential utility libraries.
There are many implentations in different languages. There are versions for C# and of course JavaScript.
You can use Mustache either in the browser or via a node module. As I have moved away from single page apps and static web sites I use Mustache in the nodejs lambdas used to render my site pages. The code is the same, but make sure to reference mustache in your node module
const template = require("mustache");
let html = template.render(blogItem, { });
Another feature is the syntax. Mustache is easy to master. Mustache fields are surrounded by {{}}. You can create loops and a crude way to do if statements.
Like I stated earlier JavaScript templatiing involves merging either an Array or JavaScript object with a template. Template libraries like Mustache perform the merging process between template and data. Each library has their own merging syntax.
Fields are properties of a JavaScript object, JSON. For the following movie object the associated template merges the values into full HTML string.
These code examples were extracted from the Mobile Movies application I wrote several years ago for my Single Page Application book. You can still access the repository, but realize the application does not work since the API source was deprecated several years ago.
let movie = { id: "123456", title: "Die Hard", poster: "http://moviedomain.com/img/die-hard.png";, description: "lorem ipsem", "ratings": { "critics_rating": "Fresh", "critics_score": 61 } };
This markup can now be added to the DOM.
You will notice the template is wrapped in a SCRIPT tag. In this instance the script does not refer to an actual JavaScript, but is more like a defacto technique for including templates in a page.
Normally script tags block all processing when rendering a page. But here the template has a type="text/x-mustache-template", which effectively tricks the browser into not processing it like a normal JavaScript block. You could use any type you like as long as it is not recognized by the browser as JavaScript, which then makes it a blocking element.
If a template will be used multiple times during a page's life cycle you should compile it.
The following example selects the template script block using the node's innerHTML property to set the actual template markup string. This markup is then compiled to a mustache template calling the mustache compile method.
let source = document.getElementById("movie-detail-template").innerHTML, let modieDetailTemplate = template.parse(source);
Once the template is compiled you can pass the data to the template to create the merged HTML. In this example the movie object is passed to the template, which is now a function. It returns the merged markup.
var html = modieDetailTemplate(movie);
The new markup can now be inserted in the DOM.
document.querySelector(".move-details").innerHTML = html;
This is an example of a single object. What about merging an array? The template just needs to be slightly modified with the each block modifier.
Template will now iterate over a movie arrays and produce a set of markup containing elements for each movie.
Other block modifiers include if, with and comment statements. You can also make custom mustache helpers to provide functionality unique to your application. mustache also supports object paths or child properties. Modifying the template with an additional DIV to display the critics rating looks like this:
The loop syntax can also be used to execute if statements. To trigger a template when a value exists use the same loop syntax used to create the list of movies, {{#movie}}. An empty template is triggered by changing the # to ^, {{^movie}}.
Summary
Mustache is a rich JavaScript templating library that is easy to use and easy to extend. It has no dependencies on any JavaScript frameworks like jQuery, but will work nicely with third party frameworks. Using JavaScript templates is key to a successful modern web application architecture. You should adopt mustache or something similar to help you create rich modern web applications.