I’m seeing an increased interest in Handlebars.js, and I’ve been using it for a while now. So I thought why not compile the ultimate cheat sheet for you in 2024?
What is Handlebars.js?
Handlebars.js extends the Mustache templating language. According to the documentation, Mustache templates are logicless, meaning that they contain no if-else clauses or for loops. They simply expand the tags in the template and adds the values that we have provided 1.
This is where Handlebars.js comes in. Handlebars provides us with all the good things from Mustache templates, but it also gives us the ability to handle logic.
Prerequisite: Compiling the Handlebars template for an email
To actually be able to use this, we need to modify our nodemailer
setup from here to
use our plugin as the compiler. First we need to import the package at the top of our file:
const hbs = require('nodemailer-express-handlebars')
and then we need to actually use the compiler in our transporter:
transporter.use('compile', hbs({
viewEngine: {
extname: '.hbs',
layoutsDir: 'templates/',
defaultLayout: false,
partialsDir: 'templates/',
},
viewPath: 'templates/',
extName: '.hbs'
}));
This post explains more in depth the options used in.
Now every time we want to use it we can use it like this:
transporter.sendMail({
from: 'Anonymous Coder<YOUR_EMAIL>',
to: 'YOUR_EMAIL',
subject: 'Your first nodemail',
template: 'email_template',
context: {}
})
Everytime we’re introducing a new concept, this is what we will be changing:
context: {}
Variables in Handlebars
The base Handlebars templat simply contains a variable, like name
below:
<div>Welcome ! This is my first nodemail!</div>
And if we’re using this together with nodemailer
,
we can use it like this:
context: {
name: 'Anonymous Coder'
}
This will then compile into:
<div>
Welcome Anonymous Coder! This is my first nodemail!
</div>
Arrays in Handlebars
Array of strings
Let’s say we want to add an array of strings to our template, for example a list of products. The Handlebars template and example could look like this:
<div>
{{#each products}}
{{#with this}}
<h3>Product Name: {{this}}</h3>
{{/with}}
{{/each}}
</div>
And modify this with the following context:
context: {
products: ['Cool Bike', 'Great Lock']
}
Array of objects
In this example I’ll add an array of objects, for example an order template. We’ll have objects of products, for example like this:
const products = [{
productId: 1,
productName: 'Cool Bike',
price: 1050
},
{
productId: 2,
productName: 'Great Lock',
price: 35
}]
The Handlebars template and example could look like this:
<div>
{{#each products}}
{{#with this}}
<h3>Product Name: {{productName}}</h3>
<p>Price: {{price}}</p>
{{/with}}
{{/each}}
</div>
For this to work properly, we need to modify the context to:
context: {
products: [{
productId: 1,
productName: 'Cool Bike',
price: 1050
},
{
productId: 2,
productName: 'Great Lock',
price: 35
}],
}
Now specifying an array in a Handlebars template, we use
#each products
or #each <YOUR_ARRAY_IN_CONTEXT>
.
The with
-helper tells the Handlebar to evaluate the context differently,
so for example with the first object this
becomes:
const this = {
productId: 1,
productName: 'Cool Bike',
price: 1050
}
and thereafter we can use it as a JS object to get the values of each key.
Functions and custom helpers in Handlebars
Need a random number to be generated inside your Handlebars? Fear not, Handlebars has a built-in helper for that. Let’s say we have a Handlebars template that looks like this:
<p>
Random Number:
</p>
Then we can provide a function to the context like this:
context: {
getRandomNumber: function() {
return Math.floor(Math.random() * 100);
}
}
And now the Handlebars template will be compiled with different random numbers every time.
If-else statements in Handlebars
Let’s say we want to show a different message depending on the
random number. We can do that with the if
-helper. The template
could look like this:
<p>
{{#if isRandomNumberGreaterThanFifty}}
Random Number is greater than 50
{{else}}
Random Number is less than 50
{{/if}}
</p>
And the context could look like this:
context: {
isRandomNumberGreaterThanFifty: function() {
return Math.floor(Math.random() * 100) > 50;
}
}
Now we will generate a different message depending on the random number.
Wrap-up
This was a quick introduction to Handlebars.js, and I hope you found it useful. The intention is to provide a quick cheat sheet on how you can use Handlebars.js in your projects.