Thursday, September 8, 2022

Handlebars-NodeJS Template Engine | A Step By Step Guide To Using Handlebars With Your Node js App

In this article, we are going to take a look at how to use the Handlebars template engine with Node.js and Express.

What is a Template Engine?

A template engine helps us to create an HTML template with minimal code. It can inject data into an HTML template on the client side and produce the final HTML. They produce the final HTML using a template and data on the client's browser. However, some templates process data and generate the final HTML page on the server side also.

There are so many template engines available for NodeJS. Each templating engine uses a different language to define HTML templates and inject data into them.

Following is the list of important (not limited) template engines for Node.JS


As you get to know that NodeJs may have a different number of template engines available for templating. 

What are Handlebars?

Handlebars is an extension of the Mustache template language, which is mostly focused on simplicity and minimal templating. 

Getting Started

Follow the step-by-step guide to learn about how we can apply handlebars on our NodeJs and ExpressJS app:

Step 1:- Let's first create a directory named "nodejs_template_handlebars" and initialize it using the npm command.
  • mkdir nodejs_template_handlebars
  • cd nodejs_template_handlebars
  • npm init -y

Step 2:- Installing all needed modules
After initializing the project, let's set up a server using the express npm module. I'm also going to install nodemon for self-starting the server whenever any changes will occur and also install "express-handlebars" too.

npm install express --save 

npm install nodemon --save-dev

 npm install express-handlebars --save


After installing the express npm module, your "package.json" file will look like this
{
  "name": "nodejs_template_handlebars",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon server.js"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.18.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.19"
  }
}

Step 2:- Setting up a basic Express Server
After installing the needed npm modules like express and nodemon. Let's first set up the basic server. For setting up the server, let's first create a server file name "server.js". You can create a file using the following command and by using the widgets.
touch server.js

After creating the server file. Let's create a server with an error handler. For creating the server you may copy the following code:
const express = require('express')
const app = express()
const PORT = process.env.PORT || 3000

// error handler
app.use(function (err, req, res, next) {
    return res.status(500).send({
        error: true,
        message: err
    });
});

app.listen(PORT, () => {
    console.log(`Server is running at ${PORT} port`)
})

Let's run the server by using the following command:
npm start

After starting the server your server may produce the following output:
[nodemon] 2.0.19
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node server.js`
Server is running at 3000 port

CONGRATULATIONS.....You've successfully set up the Basic server.

Step 3:- Handlebars set up

After the successful setup of the server. Let's set up handlebars. As we're using "express-handlebars" for our project. Let's set up "express-handlebars".

For setting up the handlebars, first, open your "server.js" file or whatever it is you call that file and require handlebars.
const { engine } = require('express-handlebars')

After requiring the "express-handlebars" module. Make a folder named "views" on the root location. This folder may contain a sub-folder named "layouts" which may store the structure for our application.
Let's get this by example.., some websites may have the same structure or layout as their website their inner content will be replaced according to the URL. So, in that case, we may create a file inside that layouts folder and call their corresponding body data from the outside. So, instead of replacing the whole page, now we'll replace the needed content.
mkdir viewscd viewsmkdir layouts

Let's configure them as the view engine using the following code in "server.js":
// setting up the engine
app.engine('handlebars', engine())
app.set('view engine', 'handlebars')
app.set('views', './views')


Step 4:- Let's set up the Routes and Controllers
After setting up the handlebars. Let's set up the routes along with the controller. For routes and controller, I'm going to create two folder names routes and controller. Each folder may contain an "index.js" file.

For setting up the routes. Let's require the routes "index.js" file into the server file.
app.use('/', require('./routes/'))

Following is the code for the routes "index.js" file:
const router = require('express').Router()
const Controller = require('../controller')

router.get('/home', Controller.homePageController)
router.get('/main', Controller.mainPageController)

module.exports = router

I'm going to create two routes to show the use of the layouts and without layouts. Here route "/home" will show the data without the layout's file and another route "/main" will show the data with the help of the layouts folder's file.

Following is the code for their corresponding controller's "index.js" file:
const homePageController = async (req, res, next) => {
    try {
        res.render('home', {
            layout: false
        })
    } catch (error) {
        next(error)
    }
}

const mainPageController = async (req, res, next) => {
    try {
        res.render('main')
    } catch (error) {
        next(error)
    }
}

module.exports = {
    homePageController,
    mainPageController
}

In the above code, I've passed an object to the home page which may have a layout property with the value false, by default the layout value is true. If the value is false then it means that this view doesn't have any corresponding layout and will load only the view's folder file whereas if we don't have any value then it means that the corresponding view may have their layout and will load that layout and pick the data from that file.

Let's create some view files inside the views folder:

i) views/home.handlebars
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Home</title>
</head>
<body>
    <h3>Welcome</h3> to home Page without any layout!!
</body>
</html>

ii) views/main.handlebars
<h4>to main page!!</h4>

iii) views/layouts/main.handlebars
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Main</title>
</head>
<body>
    <h3>Welcome</h3> {{{body}}}
</body>
</html>

In the layout's "main.handlebars" file, I've used {{{body}}} which may take the data from their corresponding "main.handlebars" file from the views folder and show the data.


Here are the screenshots for that example




















You can also visit my GitHub repository nodejs_template_handlebars for that code in case you got any type of issue.

No comments:

Post a Comment