Using Handlebars.js to work with templates

Posted by in HTML5, Javascript and TypeScript

Let’s keep on learning Javascript, and today’s entrance is for a really cool library (the library is a must know) that I have started to used not too long (well, I leant about it when I have no option to code clean Javascript, a language I hate the most). I am talking about Handlebars.js:

Handlebars is a powerful library to work with templates, compatible with Mustache, that let you organize your code better (and even reuse it)

Using templates

Templates let you define how information are presented, and after compile it, the data you send to the template is showed as you ahve defined, saving time and resources.

In order to define a handlebars template, you must do it inside your HTML code using the tag script:

 <script type=”text/x-handlebars-template” id=”template-name”></script>

The use of templates is done by Javascript, and it’s really important to define the type, and of course, assing a name (I call it template-name) for retrieving it.

If you want to improve your knowledge about how to create handlebars templates, the best option is go to tryhandlebarsjs.com where you can see them in action, with several examples and options. I don’t want to teach you how to create a template but how to use it from Javascript (although I’m moving to TypeScript).

The first example

Let’s see Handlebars.js in action with a small excersise: let’s load a JSON data and show them when a button is click. In order to beautify the example, I will use Bootstrap, but I also will nedd the libraries jQuery, bootstrap y of course, handlebars (I have used here versión 3.0.3).

The JSON file is like this:

[
{
“Name”: “Estrella”,
“Brewery”: “Damm”,
“Style”: “Euro Lager”,
“Abv”: “5.4”,
“Ibu”: “25”,
“Favorite”: false
},
….
]

once I have all ingredients ready, let’s create the HTML template to use with Handlebars:


<script type="text/x-handlebars-template" id="template-listado">
<ul id="listado" class="list-group">
<li class="list-group-item list-group-item-info">
<h3 class="list-group-item-header">Cervezas</h3>
</li>
{{# each Beers}}
<li class="list-group-item"><a>{{Name}}</a></li>
{{/each}}
</ul>
</script>

I have followed the Handlebars instruction, and I’m using #each for creating a loop, and writting the name of each beer.

Now, the full HTML code is here:


<!DOCTYPE html>
<html lang="es">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">

<title>Beer List, by ManejandoDatos.es</title>

<link href="css/bootstrap.min.css" rel="stylesheet" />

<script src="js/handlebars-v3.0.3.js"></script>
<script src="js/jquery-1.11.1.min.js"></script>
<script src="js/bootstrap.min.js"></script>

<script type="text/x-handlebars-template" id="template-listado">
<ul id="listado" class="list-group">
<li class="list-group-item list-group-item-info">
<h3 class="list-group-item-header">Cervezas</h3>
</li>
{{# each Beers}}
<li class="list-group-item"><a>{{Name}}</a></li>
{{/each}}
</ul>
</script>

</head>

<body>
<div class="jumbotron">
<h1 class="text-center">MD y Handlebars</h1>
</div>

<div class="container">
<div class="col-md-6">
<button id="carga" class="btn btn-success">Cargar datos JSON</button>
</div>
<div class="col-md-6" id="content">
</div>

</div>
</body>
</html>

There is only one thing you miss: the Javascript code, that you can add at the end of the HTML code or in a new .js file, adding it as a reference (I have included all the code in only one file, for this time!).

The Javascript code for using handlebars.js

The code is this:


$(function() {
var stemplate = $("#template-listado").html();
var tmpl = Handlebars.compile(stemplate);

var ctx = {};

$('#carga').on('click', function (e) {
$.getJSON( 'beers.json',  { format: "json"}    )
.done(
function (data) {
//  console.log(data);
ctx.Beers = data;
var html = tmpl(ctx);
$("#content").html(html).show();
}
);
});

});

The explanation of the code is more or less simple: first, let’s retrieve the handlebars template named template-listado, and store it on a variable. Next, let’s compile the template (required by Handlebars.js). Now, let’s wait for the button to be clicked for executing the function (I have used a button because this way the reader can have a better undestanding on how to use templates and how action is done!).

Once you click on the button, the JSON data is loaded, and transfer the value to the variable ctx. Next step is creating a html variable with the compiled template and with the data to be shown. And last, load the HTML code into the DIV #content.

Showing more beer info

Although in the previous exercise  we achieve the target (to show the JSON data using a template, thnaks to Handlbars.js), there is more to do, and that’s show all the info related to a beer. So, let’s define a new template for the beer info, located in the head section and named template-dato:


<script type="text/x-handlebars-template" id="template-dato">
<div class="container">
<h1>{{Name}}</h1>
<div class="col-md-12">Brewery: <span class="label label-success">{{Brewery}}</span></div>
<div class="col-md-12">Estilo: <span class="label label-info">{{Style}}</span> - Graduaci&oacute;n: <span class="label label-danger">{{Abv}}</span></div>
</div>
</script>

Let’s write the new Javascript code, and every time the user click on a beer, the information of the beer selected will be shown.


$(function() {
var stemplate = $("#template-listado").html();
var tmpl = Handlebars.compile(stemplate);
var sdato = $("#template-dato").html();
var tmpldato = Handlebars.compile(sdato);
var ctx = {};
var masdatos = $('#masdatos');

$('#carga').on('click', function (e) {
$.getJSON( 'beers.json',  { format: "json"}    )
.done(
function (data) {
console.log(data);
ctx.Beers = data;
var html = tmpl(ctx);
$("#content").html(html).show();
refresca();
}
);
});
var refresca = function  () {
$('#listado').find('li').on('click', function (e) {
$this = $(this);
var seleccion = $this.text();
var beer; var nombre = '';
for (index = 0; index < ctx.Beers.length; ++index)
{ beer = ctx.Beers[index];
if (beer.Name == seleccion) {
var html = tmpldato(beer);
masdatos.html(html)
break;
}
}
});
}
});

Let’s explain the code: I have created a new function that once the beer info is loaded, the funcion is executed, so the events can be executed and every time you click on a beer, its information will be shown using a new template (named template-dato). The second template is loaded after the first one is loaded, waiting to be used. Once the user click on a beer, I have created a for loop in order to identify the beer selected, and once located, the second template will be applied with the beer info, and the information will be shown in the DIV prepared for the beer info.

handlebars.js

handlebars.js

Using templates is nice, but ….

But I think it not very clean to have different languages mixed, templates, HTML, Javascript, … templates that are defined before, used later, … for small apps or for creating an example can be useful, but … what if you’re creating a large web app? Of course, there is a solution that I reveal in the next entrance!

by the way, all the code is available at my GitHub.

Happy coding!