Template Engines

Dynamically adding and manipulating chunks of the DOM based on data can be a tedious, error-prone activity when we try to manually create HTML strings out of data, like this:

The better way is to use a template that provides a way to dynamically add data on a set HTML structure, preventing us from having to type out these monster strings of data and markup.

We could build out our own template for each section of our blog, creating a new function for each part, and that would work, but there are tools out there to make this task nice and easy for us.

Lodash is a JavaScript library that provides a lot of utilities for working with arrays, objects, and strings, including a template library which is what we'll be working with today.

... string is our template. It's not very pretty, but it's ours. We load data into the template by closing the string and concatenating variables then continuing the template string. If you're anything like me, you've forgotten to type at least one of the plus signs nearly every time you've done any long string concatenation, so, bare minimum, our templating tool should fix this problem.

Basic Templating With Interpolation

Let's wire up a basic comments form to our blog post. Starting with the markup in index.html, we'll add a simple form, and a placeholder for the comments to be displayed.

<article>
  <header><h2>The Results are In!h2>header>
  <p>
    After careful consideration and a generous grant from NASA, our team has determined that a woodchuck could chuck five wood, with a standard deviation of +/- .37 wood.
  p>
  <footer>posted by Chuck Woodenfooter>
  <form onsubmit="postComment();return false;">
    Name: <input type="text" id="commenterName"><br>
    Comment: <input type="textarea" id="commentText"><br>
    <input type="submit">
  form>
  <div id="comments">div>
article>

So we have a basic form that will submit with a postComment() function. Let's add the basic bits of that to our index.js.

function postComment() {
  let commenter = document.getElementById('commenterName').value;
  let comment = document.getElementById('commentText').value;
  //insert comment into "comments" div in this format:
  //
}

We know the format of the template we want, but instead of adding it using string concatenation, we're going to use the lodash template function.

Top-tip: By default, we access lodash functions through the underscore, which is a variable that holds the root object, like _.template(). This is similar to accessing jQuery functions via the $ variable. This is because lodash was originally a fork of the Underscore.js library.

We'll start by building a template string as we have in the past, but instead of concatenation, we'll be using interpolation, which is a way to replace text in strings using special delimiters.

In lodash, we can interpolate strings with the <%= %> delimiter, so let's try it out.

function postComment() {
  let commenter = document.getElementById('commenterName').value;
  let comment = document.getElementById('commentText').value;
  //insert comment into "comments" div in this format:
  //

  let commentTemplate =
    '';
}

We're creating a new variable called commentTemplate that will hold our template string. We've wrapped our two variables inside the interpolation delimiters, with <%= comment %> and <%= commenter %>.

The next step is to use the template() function of lodash to turn this template string into a function that we can call with a JSON argument for the variable values.

function postComment() {
  let commenter = document.getElementById('commenterName').value;
  let comment = document.getElementById('commentText').value;
  //insert comment into "comments" div in this format:
  //

  //create template string
  let commentTemplate =
    '';
  //create template function
  let templateFn = _.template(commentTemplate);
}

We create a function here by executing _.template(), but we don't execute it now. Why?

One of the reasons to use templating is to be able to reuse the templates. By creating a function and holding it in a variable, we can execute the function over and over with different data, rather than having to rebuild the template function every time.

Now that we have our function, we'll need to execute it with our form data as a regular JSON object: { 'comment': value, 'commenter': value }. Note that the keys for the object match the variable names inside our interpolation delimiters.

Executing the function will return a string, which we can then append to our comments div. Let's finish it out.

function postComment() {
  let commenter = document.getElementById('commenterName').value;
  let comment = document.getElementById('commentText').value;
  //insert comment into "comments" div in this format:
  //

  //create template string
  let commentTemplate =
    '';
  //create template function
  let templateFn = _.template(commentTemplate);

  let commentsDiv = document.getElementById('comments');

  //execute template function with JSON object for the interpolated values
  let templateHTML = templateFn({ comment: comment, commenter: commenter });

  //append rather than replace!
  commentsDiv.innerHTML += templateHTML;
}

Reload your index.html and see it in action!

Okay, this is all fine and good, and we aren't concatenating strings anymore, but we're still building out a huge string for the template, and this is a pretty simple template. What happens when we have a lot of markup to work with?

HTML Templates in JavaScript

Putting our templates in a string isn't great for a couple of reasons. We don't get the human-readable, indented structure of regular HTML. We don't get the syntax highlighting on the tags that our editor provides. Adding or changing HTML inside a string is difficult and prone to error. What we need is a way to use a regular chunk of HTML as our template.

Fortunately, lodash gives us a great way to do this. We can use a special

Clone: https://github.com/learn-co-curriculum/js-templates-template-engines-readme

Last updated