by Nicole Zhu

If you’re a web developer learning JavaScript today, chances are you’ve heard of the common buzzwords and discussions around the latest and trendiest templating libraries and frameworks. Common ones are React, Vue.js, Angular, Backbone, Mustache, Handlebars, so on and so forth (as well as the plethora of opinions that accompany them). But what exactly is a user interface (UI) templating library? What features do different libraries give you? What makes one library better than another? Here’s a brief primer on JavaScript UI templating libraries, why they’re useful, and how to start using them in your projects. In addition to simplifying your workflow, you’ll also learn how templating libraries connect to best practices in web development.

What is a UI templating library?

NPR Book Concierge page

Every year (since 2013), NPR puts out this amazing interactive project called NPR’s Book Concierge, which is a huge collection of book recommendations from their staff and critics. All the books are shown in a large image grid that you can filter. Each book recommendation contains a brief review, an author, tags, links to other articles and features on their website, ways to check out or purchase the book, and ways to share the recommendation on social media.

book detail page

If we were to build our own simplified book concierge without the help of a templating library, we’d end up with a lot of copying and pasting of the same <div> that represents a book recommendation.

<div class="book">
  <div class="book-cover">
    <img src="images/homegoing.jpg" />
  </div>
  <div class="book-text">
    <h4>Homegoing</h4>
    <p class="author">by Yaa Gyasi</p>
    <p class="review">A stunning book that spans continents and generations!</p>
    <p class="reviewer">Recommended by Nicole Zhu</p>
  </div>
</div>

Even worse, we’d have an incredibly long HTML file, and each recommendation would have its information hardcoded. If we had fifty book recommendations, we’d have to painstakingly copy, paste, and customize each and every div throughout the entire file! Sounds super tedious, right?

This is where templating libraries save the day!

A UI templating library is a collection of pre-written functions that simplifies the process of writing HTML pages (or any kind of structured text), particularly ones with interactivity or content that changes. It does this by separating what you’re rendering on the page from how you’re rendering it. You define the content, also known as the data, and the structure and styling of that content, also known as the presentation, which the template facilitates.

Our book concierge example above illustrates this difference: we can separate the data that represents a book recommendation (i.e. the book image, title, author, tags, etc.) from the way that data appears when styled on the page or how users can interact with it. In the template, we can define the HTML structure for a book recommendation once, and the templating library will do the job of putting those pieces together and dynamically generating all the HTML.

To demonstrate how a UI templating library conceptually works, we’ll start by separating the data from the presentation by declaring our content as a set of variables. (Note: this first example is for illustrative purposes; subsequent examples will use working code.)

var bookImage = 'homegoing.jpg';
var bookTitle = 'Homegoing';
var bookAuthor = 'Yaa Gyasi';
var bookReview = 'A stunning book that spans continents and generations!';
var bookReviewer = ‘Nicole Zhu’;

Now, we’ll write out our template:

<div class="book">
  <div class="book-cover">
   <img src="/images/{{bookImage}}" />
  </div>
  <div class="book-text">
    <h4>{{bookTitle}}</h4>
    <p class="author">by {{bookAuthor}}</p>
    <p class="review">{{bookReview}}</p>
    <p class="reviewer">Recommended by {{bookReviewer}}</p>
  </div>
</div>

You’ll notice in our example above this basically looks like HTML with many of these things inserted: {{bookVariable}}. These curly braces simply denote a placeholder that can stand in for data or logic in the template, and is the way several libraries, such as Mustache, Handlebars, and RactiveJS, know where data substitution needs to happen. Mustache is a popular templating library—other commonly-used libraries such as Handlebars are built off of it and extend its capabilities. The rest of this article will use RactiveJS, which in turn builds on Handlebars, in our code samples in order to demonstrate all the various features that may be common to other libraries.

Just like we use variables in math, the placeholders are variables for the content or logic you’re loading in. When you load a page, a substitution happens in your browser which processes and translates the template, and does a sort of find and replace of its own to correctly add data to the template. So when we write something like {{bookTitle}}, that placeholder will eventually be replaced with whatever value {{bookTitle}} is in the data source, and then rendered on the page as expected.

Placeholders are one of the main features of all UI templating libraries. Using them as substitutions for real values from your data makes your code less repetitive and less reliant on hard-coding the HTML.

<h4>Homegoing</h4>

can be rewritten as

<h4>{{bookTitle}}</h4>

You can even render text that isn’t meant to be displayed to the user, such as paths or links, dynamically using placeholders. For example, if we wanted to load in the image of the book cover for our recommendation, using a relative path in our project directory so you didn’t have to hardcode the full image path every time, we’d write:

<img src="”/images/{{bookImage}}/”" />

Overall, UI templating libraries generate web pages that reuse static elements and allow dynamic elements to update without re-rendering the entire page when data changes.

What features do different UI templating libraries have?

The library landscape is huge, and each library has its tradeoffs and unique capabilities. Some libraries work best with simple data that doesn’t change much, like Mustache, while others that work better for more complex data and interactions require using an entire framework that may take more overhead and time to set up, like React. The list below is just a sampling of some of the most useful features libraries have.

Now that you have an understanding of the core feature of placeholders, let’s dive back into our book concierge example with the following data, represented as a JSON (JavaScript Object Notation) object that represents one book recommendation. JSON is a simple way to store information in properties of key/value pairs represented as “name”: “value” where the value can be any JavaScript data type i.e. a string, number, array, or even another object. To start, we’ll set our data to be a singular book object, which is a JSON object representing the different properties of a book recommendation.

data: {
  book: {
          image: 'images/homegoing.jpg',
          title: 'Homegoing',
          author: { firstName: 'Yaa', lastName: 'Gyasi'},
          tags: [
            { name: 'Historical fiction', slug: 'historical-fiction' },
            { name: 'Realistic fiction', slug: 'realistic-fiction' },
            { name: 'Staff picks', slug: 'staff-picks' }
          ],
          review: 'A stunning book that covers continents and generations!',
          reviewer: 'Nicole Zhu'
  }
}

Paths and nested properties

Think of paths as the pathways to the data you want. Some libraries like Mustache only allow simple paths, which means the structure of the data source is also relatively simple. Let’s take the following JSON object as an example:

data: {
  bookTitle: ‘Homegoing’,
  bookAuthor: ‘Yaa Gyasi’
}

The data source contains only one level of key/value pairs — the value for a given key is not another nested object, but the actual values for bookTitle and bookAuthor that we want. The simple path for getting the book’s title would be calling {{bookTitle}} from the template, the value of which is the string ‘Homegoing’.

Our book object introduced in the beginning of this section, which represents a book recommendation, is an example of a more complicated object with nested paths—for example, the value of author is, in fact, another object! That object contains the key/value pairs for the firstName and lastName properties, which means we cannot use simple paths to access those properties.

Other libraries like Handlebars and RactiveJS do allow nested paths, which makes it possible to work with more complex structured data, like JSON objects with more intense layers of nesting. In our example book object above, if we only wanted to display the author’s first name, we’d call something like this in the template: {{book.author.firstName}}, which is the path to the data we want to access.

Sections

Most libraries have ways to specify in the template how or whether to render sections of markup (possibly multiple sections), depending on the current data.

Let’s add another book recommendation to our example, and do some restructuring of our data so that it will be easier to parse and work with. In our example, we now set our data to be an array of books, which contains two JSON objects that each represent a book recommendation.

data: {
  books: [
    {
      image: 'images/homegoing.jpg',
      title: 'Homegoing',
      author: { firstName: 'Yaa', lastName: 'Gyasi'},
      tags: [
        { name: 'Historical fiction', slug: 'historical-fiction' },
        { name: 'Realistic fiction', slug: 'realistic-fiction' },
        { name: 'Staff picks', slug: 'staff-picks' }
      ],
      review: 'A stunning book that covers continents and generations!',
      reviewer: 'Nicole Zhu'
    },
    {
      title: 'Bad Feminist',
      author: { firstName: 'Roxane', lastName: 'Gay'},
      tags: [
        { name: 'Memoir', slug: 'memoir' },
        { name: 'Essays', slug: 'essays' },
        { name: 'Staff picks', slug: 'staff-picks' }
      ],
      review: 'Insightful, reflective, and funny — a must-read!',
      reviewer: 'Nicole Zhu'
    }
  ]
}

You can use loops to render list items, and the context for the section you write will iterate through the data you provide to produce the relevant markup. This is how we would render all of our book recommendations using a loop. We can render the template multiple times in the context of books:

**{{#each books}}**
  <div class="book">
    <div class="book-cover">
    <img src="{{image}}" />
  </div>
  <div class="book-text">
    <h4>{{title}}</h4>
    <p class="author">by {{author.firstName}} {{author.lastName}}</p>
    <p class="tags">
      **{{#each tags}}**
      <a href="#/tag/{{slug}}">{{name}}</a>
      **{{/each}}**
    </p>
    <p class="review">{{review}}</p>
    <p class="reviewer">Recommended by {{reviewer}}</p>
    </div>
  </div>
**{{/each}}**

You’ll see that we can even nest loops within loops. In this instance, the tags property of each book recommendation is also an array, so we can use another loop to simplify the rendering of that markup (and allow for a flexible number of tags).

<p class="tags">
  <a href="#/tag/{{tags&#91;0&#93;.slug}}">{{tags[0].name}}</a>
  <a href="#/tag/{{tags&#91;1&#93;.slug}}">{{tags[1].name}}</a>
  <a href="#/tag/{{tags&#91;2&#93;.slug}}">{{tags[2].name}}</a>
</p>

can be rewritten as

<p class="tags">
  {{#each book.tags}}
  <a href="#/tag/{{slug}}">{{name}}</a>
  {{/each}}
</p>

In addition to loops, conditionals like if/else can be used within templates to define sections. For example, we could test for the presence of data in order to determine whether we should render markup for that data. Our second book recommendation doesn’t have an image, so we can add logic to the template that checks the data and only attempt to load and render the image if such an asset exists.

{{#each books}}
<div class="book">
  **{{#if image}}**
  <div class="book-cover">
    <img src="{{image}}" />
  </div>
  **{{/if}}**
  <div class="book-text">
  ...
  </div>
</div>
{{/each}}

Partials

Even though templating cuts down on the repetitive code you write, there are still some cases where you might want to break a template down even further into what we call partials. Partials are basically mini templates that are used within other templates, or even used repeatedly within a single larger template. In the case of our book concierge, if we had lengthier and more complex markup to render and style our tags for filtering, we could turn those into a partial.

In RactiveJS, you declare a partial by wrapping the repeated code within a {{#partial}} block that declares the partial’s name:

{{#partial partialName}}
Your code for the partial goes here!
{{/partial}}
{{#each books}}
<div class="book">
  **{{#partial tag}}**
  <span class="tag"><a href="#/tag/{{slug}}">{{name}}</a></span>
  **{{/partial}}**
  ...
  <p class="tags">
    {{#each tags}}
    **{{&gt;tag}}**
    {{/each}}
  </p>
</div>
{{/each}}

Helpers

Helpers are smaller functions that you can write, that do a specific action and can be included in your templates to help with things like formatting the data to be rendered. Different libraries have their own specifications for how to write helper functions—in our example below, you’ll see we’ve added a new helper function called fullName, which returns the author’s full name by concatenating their first and last names. Helper functions help make sure your data is separated more fully from their structure or rendering, allowing for maximum flexibility for how your data is used across your app.

<p class="author">by {{author.firstName}} {{author.lastName}}</p>

can be rewritten as

<p class="author">by {{fullName(author)}}</p>
data: {
  books: [{...}, {...}],
  **fullName**: function(author) {
    return author.firstName + ' ' + author.lastName;
  }
}

Why use a UI templating library?

Don’t Repeat Yourself (DRY)

Through the various features we covered in the previous section, templating libraries reduce repetitive or redundant code that accomplishes the same goal. Updates to UI elements thus change minimally in a more predictable manner, so updates or code refactors don’t mean a massive undertaking of grunt work to find and replace elements that are all logically the same or rendered the same.

It makes your workflow so much simpler

As we saw above, UI templating libraries get rid of tedious and repetitive tasks by making the rendering and updating of dynamic content much simpler than plain HTML and JavaScript. Rather than having to concatenate HTML and append finished elements to the DOM in a JavaScript file, you can define a template and a data source and let the library do the concatenation and DOM work for you. This simplifies and minimizes the amount of code you need to write, especially if the data or content you’re rendering is constantly changing or if you need to use the same code for different purposes. If we wanted to build a book concierge every year like NPR does, we could very readily just use the same template and update the data source! After all, your time is much better spent on other things than copy/paste and find/replace.

Your teammates will thank you

Templating libraries make working on larger projects with multiple people easier and faster. If you use version control like GitHub, rather than having to constantly git pull or resolve merge conflicts because you’re all working in the same mega HTML or JavaScript file, you can break down different parts of the code and work on them separately. You can also create multiple templates that are as granular as you need, so a project can be extended and worked on in parallel without people stepping on each other’s toes. When you’re writing code as a team, it helps to standardize your approaches and formats to writing code. By using a templating library, your group can make sure the code is consistent and well-documented.

Templating libraries are also great for adding flexibility by making your code easily extendable. As the project grows, you or other developers can more easily refactor or break apart large templates into smaller files (or partials). By taking on a more component-driven approach, it will help you build out other features in the future. For example, if we wanted to make our book concierge into a multi-page app instead of a single-page app, it would be straightforward to break out our navigation bar or footer into a separate partial, which could then be included in any page with minimal repetitive code.

Readability and maintainability

Smaller files that keep the data and templates separate are easier to read than long HTML and JavaScript files that are connected in more convoluted ways. You can name your data and markup (like classes and ids) in ways that are more descriptive and specific to the context, which will make it easier for other developers to read and more quickly understand the code. In all of our examples, we’ve named our data books rather than just a generic term data because it’s more specific and meaningful to the book concierge project.

Additionally, a project is much easier to maintain if code is well-organized, readable, and concise.

How do I get started with a UI templating library?

First, assess your project and what you need. Then, do some library spelunking on the internet to see which library out there best suits your needs. Err on the side of simplicity. If you have a relatively simple data source that doesn’t require a lot of interactivity, the templating that Mustache uses (“logic-less,” i.e. it doesn’t allow for explicit use of control flow statements) might be the right choice for you. If your project has more interactivity, more computed properties and complex data, or if you envision growing into a more dynamic application overall, a library like RactiveJS or AngularJS might be better choices. All of these libraries have good documentation and guides for using them in your own projects.

The easiest way to get set up with a UI templating library is to include the necessary files for loading that library in your HTML file, create a template according to that library’s specifications, add and structure your data, and load your data into the template. If you’re using a package manager for your project, such as NPM or Bower, you can install the module (library) via a command-line utility, and then continue adding your data and creating a template within your project directory.

Here is our example in full in RactiveJS.

Finally, feel free to try out different libraries in different situations! There are many other UI templating libraries with unique capabilities that were not covered in-depth in this article. Don’t be afraid to try something new or refactor the same code to see how using a different library makes your life easier. As you gain more experience working with templating libraries, you’ll learn which ones work for you.

Catch you temp-later!

REFERENCES

Nicole Zhu is a writer and developer based in New York. She is an engineer on the publishing team at Vox Media and is the co-host of Sweet and Sour, a podcast that explores the common threads and nuances of the Asian American experience.