Reducing repetition in HTML templates

Don't Repeat Yourself (DRY) is an important principle in software development.

Code repetition harms maintainability by making it difficult to keep behavior consistent across the application.

Read this article to learn about a common repetition problem in HTML code and how to resolve it.

The problem: template code with repetitions

How would you build a form like this?

Image of a form with 4 fields

Directly writing the HTML for each form field is the most obvious solution:

<div class="form-field">
     <label>First Name</label>
     <input type="text" name="firstName"></input>
</div>
<div class="form-field">
     <label>Last Name</label>
     <input type="text" name="lastName"></input>
</div>
<div class="form-field">
     <label>City</label>
     <input type="text" name="city"></input>
</div>
<div class="form-field">
     <label>Country</label>
     <input type="text" country="country"></input>
</div>

However, as you can see above, this involves a lot of repetition. Only the title and the name are different for each form field!

As a result, if you wanted to add a new class to the label, you'd have to change the code in four different places.

Eliminating HTML repetition

To fix this problem, we have to separate the HTML structure from the content we want to display. The underlying HTML structure is the same for each form field.

For example, the content above could be represented by this JavaScript object:

var formFields = [{
    title: "First Name",
    name: "firstName"
}, {
    title: "Last Name",
    name: "lastName"
}, {
    title: "City",
    name: "city"
}, {
    title: "Country",
    name: "country"
}];

For each field we want the following HTML code:

<div class="form-field">
     <label>{{title}}</label>
     <input type="text" name="{{name}}"></input>
</div>

{{title}} and {{name}} are placeholders for our content data.

We need to join these two bits of information together using a template engine like Mustache or Handlebars.

Feel free to play around with the final code.

Note how it uses the template language to iterate over the formFields array:

{{#formFields}}
    <div class="form-field">
         <label>{{title}}</label>
         <input type="text" name="{{name}}"></input>
    </div>
{{/formFields}}

And then renders the template:

 Mustache.render(template, {formFields: formFields});

Now it's easy to add another form field or modify each field's HTML code. Adding a new field is as simple as adding a new item to the formFields array. Modifying the template will make sure that the HTML for each form field is updated consistently.

As an additional benefit, the form HTML could also be re-used for other forms using the same DOM structure.