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!