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 filesWarning
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__dirnamebuilt-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 pathRead 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 lighterOur 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 therequest.body - We can create an object to store these
request.body.semesterandrequest.body.teacher - Or we can use destructuring on
request.bodyto 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:andTeacher:, these values are store in body asrequest.body.semesterandrequest.body.teacher semesterandteacherbecause of the placeholdername="semester"andname="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 calledsemester<%= teacher %>means that we gonna replace THIS with an variable calledteacher
<!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>