Handlebars.js

All about Handlebars.js


Template Engines πŸ”­

Express supports template engines such as Pug, EJS, and Handlebars, among others. Called Dynamic HTMLs.

  • Useful for reusing repeating HTML layouts in different HTML files in our project and allows us to use JS code into HTML
  • So useful!!

Suppose an user access the route /. Our function app.get can render html by passing into the response.render() along with any data or variable.

app.get("/", (request, response) => {
  const variables = {
    semester: "Summer",
    greeting: "Welcome to the course site"
  }
  response.render("welcome", variables); // Passing variables to welcome.html
});

The semester and greeting variables are passed to welcome.html

// welcome.html
<body>
  <h1>Introduction (<%= semester %>)</h1>
  <p>The usual greeting is <%= greeting %> </p>
</body>

Set Up Template Engines

  • In order to use a template engine, we must set this up to our app
  • We gonna use app.set(), which means "set up this to our app"

To specify the engine template, we gonna do two things:

  • Set template engine extension: .ejs (from handlerbars)s
  • Set the folder where EJS files will be located
const express = require('express')
const app = express()
 
app.set('view engine', '.ejs') // set extension ejs
app.set('views', './pages') // In pages folder are our ejs files

Warning

If you are working on macOS or Windows, use path.resolve which will give you the full path no matter what OS you working on. This might fix some issues when working with macOS or Windows on the same project.

The path.resolve() takes two arguments:

  • pathToProject - full path of your project. Use __dirname built-in node variable.
  • folder - the folder where your HTMLs/Template Engine are located
const path = require('path') //necessary for resolve()
 
const FULLPATH = path.resolve(__dirname, './pages')
app.set('view engine', '.ejs') // set extension ejs
app.set('views', FULLPATH) // resolved path

Read Input from Forms/Send Data with Template Engine πŸ“–

Used to parse the data that comes from an HTML form submission. Specifically, it parses application/x-www-form-urlencoded data, which is the default content type when submitting forms via the POST method.

const express = require('express')
const app = express()
const bodyParser = require('body-parser')
 
// app.use(express.urlencoded({extended:true}))
// If expected forms with complex/nested data -> extended: true
 
app.use(bodyParser.urlencoded({extended:false}));
// if don’t need to parse complex, nested objects, it keeps the middleware lighter

Our app now can read inputs from user forms, but how can we catch those inputs?

  • In a method post (meaning when an user press a submit button), the user inputs will be saved in the body, specifically in the request.body
  • We can create an object to store these request.body.semester and request.body.teacher
  • Or we can use destructuring on request.body to get these inputs (preference)
app.post("/". (request,resposne) => {
  // Using destructuring - Preference
  // const {semester,teacher} = request.body
  
  // Using object - Instructor notes
  const variables = 
  {
	semester: request.body.semester,
	teacher: request.body.teacher
  },
  // Generate HTML and passing this variables
  response.render("courseInfo", variables);
})

But, you may ask, How do I actually know the user's inputs are called semester and teacher and are store in the request.body? The answer: the name attribute!!

  • Note that when user fill the fields Semeter: and Teacher:, these values are store in body as request.body.semester and request.body.teacher
  • semester and teacher because of the placeholder name="semester" and name="teacher" respectively.
  • This is how we catch these values into our index.js - app.post()
<form action="http://localhost:7003/" method="post">
  <strong>Semester: </strong><input type="text" name="semester">
  <strong>Teacher: </strong><input type="text" name="teacher">
  <input type="submit" value="Submit Data">
</form>

Now that we have access to user inputs, we can send these variables to another HTML. In brief, semester and teacher from the form will go thru app.post(), then app.post() will catch these variables and will send to another HTML using the template engine EJS.

  • <%= semester %> means that we gonna replace THIS with an variable called semester
  • <%= teacher %> means that we gonna replace THIS with an variable called teacher
<!doctype html>
<html lang="en">
  <head>
  <title>Course Web Page</title>
  <meta charset="utf-8" />
</head>
 
<body>
  <h1>Course Information</h1>
  <p> 
	  Additional information for the 
	  <strong> <%= semester %> </strong> semester taught by 
	  <strong> <%= teacher %> </strong> is available on the CS Dept web site.
  </p>
</body>
</html>