A Step By Step Guide To Using Handlebars With Your Node js App
By: Wael Yasmina
Tags: Nodejs, Backend Development, Expressjs, Backend, Handlebars

Since our “main.handlebars” file is empty if you try to run the app and look at the result nothing will show up since neither our “main.handlebars” nor “index.handlebars”’s body contain anything, so let’s open the “main.handlebars” file and fill it with some content:

<h2>Liste of my most loved League champions</h2>

<ul>

<li class="midlaner">Leblanc</li>

<li class="midlaner">Lux</li>

<li class="toplaner">Teemo</li>

<li class="midlaner">Kassadin</li>

<li class="toplaner">Jarvan IV</li>

</ul>

Let’s add some CSS:

li {

font-size: 2rem;

width: 300px;

margin: 4px;

padding: 4px;

list-style: none

} .midlaner {background-color: #eeeeee} .toplaner {background-color: #ffea00}

By now if you refresh the page, you will see some content (probably not interesting enough to catch your eyes).

Handlebars Configuration

extname: string

The first thing it came to my mind and I’m pretty sure it was the same for you when you were about to create handlebars file is “Uhm that’s a heck of a big file extension” and that’s where our first configuration property comes in handy.

Let’s change the code so our file extension will take fewer characters, “.hbs” for instance looks good to me:

//instead of app.set('view engine', 'handlebars');

app.set('view engine', 'hbs'); //instead of app.engine('handlebars', handlebars({

app.engine('hbs', handlebars({

layoutsDir: __dirname + '/views/layouts',

//new configuration parameter

extname: 'hbs'

}));

Don’t forget to change the extension of the files we already created (“main.handlebars” to “main.hbs” and “index.handlebars” to “index.hbs”).

defaultLayout: string

By default, if you don’t tell handlebars which layout file to render, it will throw an error telling you there’s no layout file. Using this property will give you the control to what name of the file it has to look for in case you didn’t explicitly mention it in the render function.

Let’s create a file and name it “planB.hbs” and let’s fill it with something different:

<!DOCTYPE html>

<html lang="en">

<head>

<meta charset="utf-8" />

<meta http-equiv="X-UA-Compatible" content="IE=edge" />

<title>My Awesome App</title>

<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />

<link rel="stylesheet" type="text/css" href="./style.css" />

</head>

<body>

<h1>This is the plan B page</h1>

{{!-- We could use the same body as the index.hbs page --}}

{{!-- using the {{{body}}}, you remember it right ?--}}

</body>

</html>

Let’s add the new property to our “index.js” file:

app.engine('hbs', handlebars({

layoutsDir: __dirname + '/views/layouts',

extname: 'hbs',

//new configuration parameter

defaultLayout: 'planB',

})); app.get('/', (req, res) => {

//instead of res.render('main', {layout: 'index'});

res.render('main');

});

I guess you predicted correctly what we will be getting after running the code, didn’t you?

Keep in mind that adding the property with a name of a file let’s say “file1.hbs” as value will be overwritten if you mention explicitly another file “file2.hbs” in the render function, in other words, the file mentioned in the render function has the priority to be rendered over the one mentioned in the defaultLayout property.

partialsDir: string

This property helps to make the project more organized, it takes a string path to a folder as a value, this folder will contain small chunks of code that we can use in the body of our “main.hbs”, “index.hbs” or any other partial file (a partial nested inside another one). It’s the same idea of the component-based frameworks such as React.

Let’s create two files in the subfolder named “partials” that we created earlier and call them “lovedChamps.hbs” and “hatedChamps.hbs”.

Cut the code inside the “main.hbs” file and paste it inside the “lovedChamps.hbs” and let’s create another list inside the “hatedChamps.hbs”.

“main.hbs”:

{{> lovedChamps}}

{{> hatedChamps}}

As you can see we’re referring to the files containing the code we want to include to our core code by this notation {{> partial_name}}.

“lovedChamps.hbs”:

<h2>Liste of my most loved League champions</h2>

<ul>

<li class="midlaner">Leblanc</li>

<li class="midlaner">Lux</li>

<li class="toplaner">Teemo</li>

<li class="midlaner">Kassadin</li>

<li class="toplaner">Jarvan IV</li>

</ul>

“hatedChamps.hbs”:

<h2>Liste of my most hated League champions</h2>

<ul>

<li class="midlaner">Yasuo</li>

<li class="midlaner">Zoe</li>

<li class="toplaner">Mundo</li>

<li class="toplaner">Darius</li>

<li class="midlaner">Fizz</li>

</ul>

“index.js”:

app.engine('hbs', handlebars({

layoutsDir: __dirname + '/views/layouts',

extname: 'hbs',

defaultLayout: 'planB',

//new configuration parameter

partialsDir: __dirname + '/views/partials/'

})); app.get('/', (req, res) => {

//Using the index.hbs file instead of planB

res.render('main', {layout: 'index'});});

Run this and see magic happens.