Mustache: Bloody Brilliant

Moving data structures to fill HTML elements.

In short:

  • Brilliant Documentation
  • Obvious how to use
  • Solves a tricky issue

So straight up, here is the documentation for JS: https://github.com/janl/mustache.js/

It is good. If you have data, want a site and are confident, have a look. If you don’t know what I am talking about, read on.

My explanation

The problem it solves

If you are given data (or have an API response), the data will come in a format. That format will be repeated again and again. It could be:

const jsonData = 
{ data: [
{ name : "Alice", likes : ["apples","archery"] },
{ name : "Becky", likes : ["beagles","boxing", "bodyboarding"] },
{ name : "Charlie", likes : ["cheese", "chess"] }
]
}

It could be the most convoluted, nested mess. [Side note, if it is a mess GraphQL could help.]

In either case, we would likely want to render this info to the user within a nice UI. Now we have an immediate problem. If you have only learnt standard HTML and CSS / were building a static site, you may not know a way to do this — at least I didn’t.

Use mustache.js.

What do you need to put in?

What mustache requires is a template, a script and a target.

Template: where you tell it where to put the data. Essentially make the HTML element as you want it, with the styling you want and label sections / remember what bits need to be filled with the data you would want. Use dummy data here to get the styling right. For example:

<div>
<h1> This is Name </h1>
<h3>Name likes:</h3>
<ul><li>Item1</li><li>Item2</li></ul>
</div>

Note: if you don’t recognise <ul><li> it is the HTML tag for unstructured lists.

Script: this is where you tell mustache where the data is (“my data object is called this”), where the template is, and the target location on your page that you want the filled templates to appear.

This last bit uses the getElementById() function build in to JS. What this does is scan your DOM (basically* your html document) and find any elements that have the id which you have entered. Unless you want the data in multiple places (?!), don’t have the ID fields the same.

*I am massively simplifying for this; do read up on what a DOM is here.

Target: this is simply a label somewhere in your html so Mustache knows where to input the new elements. For example, should this data go in your banner, nav bar or the actual body. Mustache won’t know until you tell it.

Oh! Also don’t forget to add the Mustache script on your site’s page!

<script src="https://cdnjs.cloudflare.com/ajax/libs/mustache.js/3.0.0/mustache.js" type="text/x-mustache-template"></script>

What does this code actually look like then?

The template part

Sweet. Now that we understand what the intent is let’s read some code. First up, the Template which goes in your HTML file:

<script id="emptyTemplate" type="text/html">{{#data}}Hello {{ name }}!<br><p>{{likes}}</p><br>{{/data}}</script>

There are a few odd things here. In fact there is a lot.

First, the Template is in a script tag <script …. Why? I am not 100% sure but I think it is so Mustache can connect to it easier. This is the way the Mustache documentation suggests to do it.

Second is that type="text/html". Now this something I have added. I use VS code and adding this makes the formatting apply. Why because you are saying the contents of this tag is of the html type.

Note the difference type makes. Ignore the code in here though! It is just an example.

It does do more than just format though. There is no function and no output from this tscript tag. As such, it is a bit of a waste of resources. As such, we may not want this to happen so we aren’t wasteful. If so we change type to text/x-mustache-template and now it will not be run. Doing this though confuses VS code and so it doesn’t apply formatting. It is up to you, but during dev I would have the formatting on as it can help!

Third weird thing: {{#data}}. This is our first sight of a mustache! {

This signifies which array you want to go through. Remember our data structure from earlier. We are replicating that here with {{ tags.

{ data: [
{ name : "Alice", likes : ["apples","archery"] },
{ name : "Becky", likes : ["beagles","boxing", "bodyboarding"] },
{ name : "Charlie", likes : ["cheese", "chess"] }
]
}
-----------
{{#data}}
Hello {{ name }}!<br><p>{{likes}}</p>

We can work with nested data structures, “if empty” logic and so much more too using the mustache documentation.

The script part

Sweet, now as before let’s first just try to read it:

function loadData(dataIn) {let template = document.getElementById("template").innerHTML;let rendered = Mustache.render(template, dataIn);document.getElementById("target").innerHTML = rendered;};

As per, the naming of the function can be anything but I have tried to be descriptive. Next I have fed data in. (Just in case, the importance here is I have defined dataIn and then given instructions of what to do with dataIn. Now anytime call the loadData function I can pass it the data, regardless of its name. In our app for example we will be calling loadData(jsonData).)

On the second line you see we define the template by document.getElementById. This retrieves the HTML content of our template. When then define the rendered content by calling on Mustache.render and passing it our data and our template.

Finally we find the target on our page and replace it with our rendered. Once again we use the getElementById() function but this time it is to find somewhere on out html where we want to insert these features. This takes the outputted html and writes over the template.

The Target part

It is as simple as this:

<div id="target">Loading...</div>

The location you want to fill with your many templates just needs an id which you can find. It doesn’t matter what you call it so long as it is the same in the script.

I have put some text in the div — Loading... Why? Well if something is going slow and your data doesn’t arrive immediately your users might see and empty page. As such, I just have a placeholder. It will get replaced when our script is finished.

Done

See that wasn’t so hard!

As a summary, build the template, label the data fields, put a target in and boom! Done.

Focused on saving our time: everyhour.xyz for your life balance; tree-meals-a-day.earth for our food emissions and compairbnb.info/hello for booking airbnbs.