Template Reuse

Compare index.hbs and search.hbs; you will notice a fair deal of duplicated HTML statements. As a principle, code duplication is something we want to avoid. So let's take a look at some best practices that will avoid duplication in your template files.

Handlebars, as well as most other templating languages, offer a way to reuse templates. This usually comes under the name of template reuse, or template inheritance, or template inclusion. It means the ability to embed part of a template into another one.

Make a new template file resources/templates/base.hbs and copy the content of index.hbs into it:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>JHU Course Search</title>
    <link rel="stylesheet" href="/style.css">
    <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
</head>
<body>
<div class="wrap">
    <div class="title">Course Search</div>
    <form class="search" action="/search" method="post">
        <input type="text" class="searchTerm" placeholder="" name="query">
        <button type="submit" class="searchButton">
            <i class="fa fa-search"></i>
        </button>
    </form>
</div>
</body>
</html>

Notice that everything from the first line, until the opening of <body> is the same in search.hbs. We will use the #block construct in handlebars to define (and later reuse) a header block:

{{#block "header" }}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>JHU Course Search</title>
        <link rel="stylesheet" href="/style.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    </head>
    <body>
{{/block }}

Moreover, the last two closing HTML tags are also common between index.hbs and search.hbs (and likely in any other template file that we may create); let's define a footer block as follows:

{{#block "footer" }}
    </body>
    </html>
{{/block }}

What changes from index.hbs to search.hbs is what comes inside the body (<body></body>); let's call that the content block:

{{#block "content" }}
{{/block }}

Note that I've left this block with no content!

At this point, the base.hbs must look like this:

{{#block "header" }}
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <title>JHU Course Search</title>
        <link rel="stylesheet" href="/style.css">
        <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.4.0/css/font-awesome.min.css">
    </head>
    <body>
{{/block }}

{{#block "content" }}
{{/block }}

{{#block "footer" }}
    </body>
    </html>
{{/block }}

Let's update index.hbs to reuse the base template:

{{#partial "content"}}
  <div class="wrap">
      <div class="title">Course Search</div>
      <form class="search" action="/search" method="post">
          <input type="text" class="searchTerm" placeholder="" name="query">
          <button type="submit" class="searchButton">
              <i class="fa fa-search"></i>
          </button>
      </form>
  </div>
{{/partial}}

{{> base.hbs}}

The {{> base.hbs}} allows reusing the base template (kind of like using extends keyword in Java). Moreover, the #partial constructs allows to add to the content block which is inherited from the base template (kind of like @Overrride in Java).

Let's update the search.hbs to reuse the base template:

{{#partial "content"}}
  <form class="search" action="/search" method="post">
      <input type="text" class="searchTerm" placeholder="" name="query">
      <button type="submit" class="searchButton">
          <i class="fa fa-search"></i>
      </button>
  </form>
  <ul class="course-list">
      <li class="course-list-item">EN.601.226 Data Structures</li>
      <li class="course-list-item">EN.601.280 Full-Stack JavaScript</li>
      <li class="course-list-item">EN.601.421 Object-Oriented Software Engineering</li>
  </ul>
{{/partial}}

{{> base.hbs}}

Rerun the WebServer and make sure our refactoring has not introduced any error; everything must work as before!