Appointment Creation and Appointment Selection Programming Worksheet

• Kiosk for picking time slot for G, G2 drive test:(Continue from assignment 3, make sure it is working
correctly)
o
o
o
o
In this application you will simulate some of the actions that you perform in Drive test
center. But here you have greater flexibility to pick the time of your choice. You will also
develop an extension of this application by adding few other user interfaces to perform
different actions. Mainly entire application consists of following parts:
1. Driver Interface (a person who wants to take G2/G license)
2. Examiner Interface (a person who takes driver’s exam)
3. Admin (a person who adds schedules and other stuff in the portal)
Assignment 4: Appointment Creation and Appointment
selection
o
o
o
In this assignment, we will add one more userType = “Admin” and allow him to create
drive test appointment slots, later Drivers can pick one of the slot and book drive test
appointment.
Day 1: (Week 10): [Day when assignment was released]: Mark 1
▪ Add new view to the application – appointment (No need to anything right now)
▪ For now, this page is also protected using user authentication, but it is only
accessible UserType = “Admin” (Ref: Book page: 95)
▪ For this you need to add one more navigation option once user login.
▪ If user is login and UserType = “Driver”, they see G2_page, G_page navigation
option
▪ If user is login and UserType = “Admin”, they see only Appointment option
▪ Also modify authMiddleware so that one applies to Driver type, and another
applies to Admin type (Page ref: 97, 98). You may choose to add two
middleware.
Day 2: (Week 11): Mark 1
▪ Create appointment View
▪ From the appointment page Admin can add appointment slots only
▪ Ie for One date there are many appointment slots can be offered (9:00 am –
2:00 pm), ie appointment times can be 9:00, 9:30, 10:00…..
▪ Simply try to create prototype first,
▪ You can save the data in Appointment collection, you can save each
appointment slot separately ({date: , time: }), it doesn’t
matter how you save time, best thing is saved as string (“9:00”)
▪ You need to add new data Model => Appointment
▪ Ie [
{date: , time: “9:00”},
{date: , time: “9:30”}
]

o
o
o
o
o
o
o
o
o
o
o
o
o
o
o
To achieve this, don’t allow admin to enter time manually, simply display time
as button or some other way
Day 3: (Week 12) Entire Assignment due [Mark 10]
From the Appointment view Admin is creating appointment slots only
Refine the Appointment page, don’t allow Admin to add same time slot for given date
Once time slot is added, gray out that button so that Admin will not add same time
multiple times etc
Make sure you don’t add same time for the same date (avoid duplicate appointment)
Now modify G2_page so when user visit this page, they can see the available time slots
for current date
For this you can add calendar to pick the Date on G2_page
Once the date is selected, display the appointment slots added by Admin
To make this work, please add few dates and time from Appointment Add view (as an
admin user)
User can pick the appointment time from G2_page and book an appointment
You need to modify the User Collection to store the Appointment ID, this way you can
establish link between User and Appointment collection
Also, you need to update the Appointment record and add some flag to verify that time
slot is available for booking or not ie isTimeSlotAvailable = false
Ie You Appointment Model would look like this:
{
Date: ,
Time: ,
isTimeSlotAvailable:
}
Now if isTimeSlotAvailable is false you don’t show them on G2_page, It means that time
slot is already booked
Summary: In this assignment, you allow the admin user to enter appointment time
slot, later display those time slots on Driver’s view and driver can select those and
book appointment time slot.
Assignment 3: User Authentication
o
o
o
o
o
o
o
o
o
o
o
o
o
o
o
o
o
Day 1 (Week 6): [Day when assignment was released]:
▪ Modify your code and add data encryption on License Number and save them to DB
[Mark 1]
Day 2: [Week 9]:
▪ Modify login page, Add signup/login. [Mark 1]
▪ When user selects SignUp => ask username, password, repeated password
▪ Also create a dropdown list UserType: Driver, Examiner, Admin
▪ From SignUp menu, user can enter username, password, repeated password, UserType
▪ Save the data in User Collection – make sure password is encrypted, you don’t need to
save password two times
▪ When you save data make sure you encrypt password, no need to save repeated
password
▪ For this you need to update the User Model, so that you can add username, password
and UserType fields
▪ You also need to modify your user model, so that at the time of signup you also add
certain default value about other fields in User Collection (firstname, lastname,
LicenseNo, Car Info)
Day 3: [Week 10] Entire Assignment due [Mark 10]
Start rearranging code appropriately in MVC pattern
Now you have completed signup part
Once signup is successful ask user to login
When user selects Login => ask for username, password
▪ There are two scenarios here:
▪ User is login first Time: In this case, all the values are default, stored using User Model
▪ User is login second Time: In this case, all the default values are updated by user supplied
values
If login is successful, now show the navigation option for G2_page, G_page, if the UserType is
Driver (Ref: Book page: 95)
After successful Login Only UserType = Driver can access the G2_Page, G_page. So appropriately
protect the path/routes
By now you can understand that previously entered User data is of NO USE. You may goto DB
and delete previous entry.
Now if you visit the G2_page and if License No is default value, You present the empty G2_page
where User can enter the information similar to Assignment_2
You also need to modify G_page, and remove search option based on License No
Simply display data on G_page based on Login user, when user is login you have all information
about user
Again, if all data are default, you can assume that User has not entered information from G2_page
By now both G2_page and G_page would check if the user data are default or not, then take user
to G2_page and offer to add all the information
If login is unsuccessful ask user to signup first
Also make sure G2_page & G_page is authenticated and only accessible by Driver only, for this
you need to add user_id (MongoDB Object ID) and user_UserType into browser’s session (Ref:
Book page: 95 – 96)
o
o
o
o
o
o
o
{
}
You need to modify the way you save data from G2_page, previously you were Inserting data into
Database. Now due to login functionality you will update the user data and offer to save extra
items to User Collection. User is already created in SignUp. You could only be able to access
G2_page, G_page only after login. Both pages are protected now using User Authentication. You
will update the User data in DB based on user_id (MongoDB) you received in login step.
If user have already entered G2 data, and login again you show those data on G2 page
You can keep the functionality of G_page as it is, and allow to be accessed by only login user with
UserType = Driver
Also incorporate validation mechanism and display common input errors (duplicate username,
empty field, License number length etc)
For this assignment you can assume that user is selecting only “Driver” – UserType from
dropdown list on the SignUp page
Summary: In this assignment, you will add user authentication and protest G2_page, G_page, so
that only login User with UserType= Driver can access this page.
Modified User Model: With only username, password and userType the rest of the fields are
default
firstname: ‘default’,
lastname: ”default”,
License No: ”default”,
Age: ‘0’,
Username: ‘demo’,
Password: ‘demo’, //Encrypted value
UserType: ‘Driver’,
car_details: {
make: ‘ default ‘,
model: ‘ default ‘,
year: ‘0’,
platno: ‘ default ‘
}
Sample SignUP/Login Page: User has not login yet, No option for G2_Page/G_Page
Sample Dashboard after user login: Option to select G2_Test, G_Test & Logout
Sample G_page after user login: User can’t modify FirstName, LastName, Age. Car Info can be modified.
No need to offer search textbox to Input License No.
Beginning Node.js,
Express & MongoDB Development
Greg Lim
Copyright © 2019 Greg Lim
All rights reserved.
COPYRIGHT © 2019 BY GREG LIM
ALL RIGHTS RESERVED.
NO PART OF THIS BOOK MAY BE REPRODUCED IN ANY FORM
OR BY ANY ELECTRONIC OR MECHANICAL MEANS INCLUDING
INFORMATION STORAGE AND RETRIEVAL SYSTEMS, WITHOUT
PERMISSION IN WRITING FROM THE AUTHOR. THE ONLY
EXCEPTION IS BY A REVIEWER, WHO MAY QUOTE SHORT
EXCERPTS IN A REVIEW.
FIRST EDITION: JULY 2019
Table of Contents
PREFACE
CHAPTER 1: INTRODUCTION
CHAPTER 2: INTRODUCTION TO NPM & EXPRESS
CHAPTER 3: BEGINNING OUR BLOG PROJECT
CHAPTER 4: TEMPLATING ENGINES
CHAPTER 5: INTRODUCTION TO MONGODB
CHAPTER 6: APPLYING MONGODB TO OUR PROJECT
CHAPTER 7: UPLOADING AN IMAGE WITH EXPRESS
CHAPTER 8: INTRODUCTION TO EXPRESS MIDDLEWARE
CHAPTER 9: REFACTORING TO MVC
CHAPTER 10: USER REGISTRATION
CHAPTER 11: USER AUTHENTICATION WITH EXPRESS SESSIONS
CHAPTER 12: SHOWING VALIDATION ERRORS
CHAPTER 13: RELATING POST COLLECTION WITH USER COLLECTION
CHAPTER 14: ADDING A WYSIWYG EDITOR
CHAPTER 15: USING MONGODB ATLAS
CHAPTER 16: DEPLOYING WEB APPS ON HEROKU
ABOUT THE AUTHOR
PREFACE
About this book
In this book, we take you on a fun, hands-on and pragmatic journey to
learning Node.js, Express and MongoDB development. You’ll start building
your first Node.js app within minutes. Every chapter is written in a bite-sized
manner and straight to the point as I don’t want to waste your time (and most
certainly mine) on the content you don’t need. In the end, you will have the
skills to create a blog app and deploy it to the Internet.
In the course of this book, we will cover:
– Chapter 1: Introduction
– Chapter 2: Introduction to npm & Express
– Chapter 3: Beginning our Blog Project
– Chapter 4: Templating Engines
– Chapter 5: Introduction to MongoDB
– Chapter 6: Applying MongoDB to our Project
– Chapter 7: Uploading an Image with Express
– Chapter 8: Introduction to Express Middleware
– Chapter 9: Refactoring to MVC
– Chapter 10: User Registration
– Chapter 11: User Authentication with Express Sessions
– Chapter 12: Showing Validation Errors
– Chapter 13: Relating Post Collection with User Collection
– Chapter 14: Adding a WYSIWYG Editor
– Chapter 15: Using MongoDB Atlas
– Chapter 16: Deploying Web Apps on Heroku
The goal of this book is to teach you Node.js, Express and MongoDB
development in a manageable way without overwhelming you. We focus
only on the essentials and cover the material in a hands-on practice manner
for you to code along.
Working Through This Book
This book is purposely broken down into sixteen short chapters where the
development process of each chapter will center on different essential topics.
The book takes a practical hands on approach to learning through practice.
You learn best when you code along with the examples in the book. Along
the way, if you encounter any problems, do drop me a mail at support@iducate.com where I will try to answer your query.
Requirements
No previous knowledge on Node.js development required, but you should
have basic programming knowledge.
Getting Book Updates
To receive updated versions of the book, subscribe to our mailing list by
sending a mail to support@i-ducate.com. I try to update my books to use the
latest version of software, libraries and will update the codes/content in this
book. So, do subscribe to my list to receive updated copies!
Code Examples
Where necessary, the relevant source codes links are posted at the end of each
chapter.
CHAPTER 1: INTRODUCTION
Node.js is one of the most popular server-side frameworks. Increasing
companies are building their applications with Node.js for example, WalMart, LinkedIn, PayPal, YouTube, Yahoo!, Amazon.com, Netflix, eBay and
Reddit. In this book, we will learn about Node.js together with Express and
MongoDB and build a blog app from scratch with them. In the process, you
will progress from a beginner to where you can build apps effectively using
these technologies.
You will learn a range of topics like user authentication, data validation,
asynchronous JavaScript, password hashing, Express, MongoDB, templating
engines, maintaining user sessions and more.
The App We Will Be Building
We will build a blog app which lets users write blog entries once they sign up
with an account (fig. 1.1, 1.2, 1.3).
Figure 1.1 – Home Page
Figure 1.2 – Register a User
Figure 1.3 – Create Blog Post Form
After the user registers, she can go to the homepage and login with her
credentials. The navigation bar will dynamically show different items
depending on the user being logged in or out. We will achieve this using the
EJS templating engine. Once logged in, the navigation bar will have a ‘ Log
Out ’ item. There will also be a ‘ New Post ’ item where the user can create a
new blog post and upload an associated image file. When she goes back to
the Home page, her blog entries will be posted there with the username and
date posted. Throughout this app, we will learn a lot of concepts and solidify
our Node.js, Express and MongoDB knowledge.
What is Node.js?
Before we understand what Node.js is, we need to understand how the
Internet works. When a user opens up her browser and makes a request to a
site, she is known as a client. The client makes a request of a certain website
to a server which upon receiving the request, responds with the content of the
requested site to the client who then displays it in her browser. For example, I
make a request to amazon.com and Amazon servers responds back with the
HTML for amazon.com.
There have been server-side programming languages like PHP, Ruby,
Python, ASP, Java and others which helps us respond to browser requests
appropriately on the server. Traditionally, JavaScript is used to run only on
the browser to provide website interactivity for example dropdown menus.
But in 2009, Node.js took V8, Google Chrome ’ s powerful JavaScript
engine, out of the browser and enabled it to run on servers. Thus, in addition
to the existing server-side languages, developers could now choose
JavaScript to develop server-side applications.
What benefits does choosing Node.js as a server-side language bring about?
– Firstly, the V8 JavaScript engine used in Google Chrome is fast and
can execute thousands of instructions a second
– Secondly, Node.js encourages an asynchronous coding style making
for faster code to manage concurrency while avoiding multithreaded
problems.
– Thirdly, because of its popularity, JavaScript offers Node.js access to
many useful libraries
– And of course, Node.js provides us the ability to share code between
browser and server since they both use JavaScript code. Based on this,
developers have created the MEAN stack, an all-JavaScript web
application stack consisting of MongoDB (a database controlled by
JavaScript) , Express, Angular (a front-end JavaScript framework – I
have in fact written a book entirely on Angular) and Node.js. Using
JavaScript everywhere is a major benefit of Node.js. In fact, there is
also a MERN stack where instead of using Angular, React is used as
the front end. In this book, we will cover MongoDB, Express and
Node.js, i.e. the MEN stack.
Installing Node.js
To install Node.js, go to nodejs.org (fig. 1.4) and download the appropriate
version for your Operating System.
Figure 1.4
Installation should be straightforward. Once Node.js has been installed, go to
your Terminal and run:
node -v
This shows the version of Node that you installed e.g. v10.15.3 (at time of
this book ’ s writing). You should also be able to run:
npm -v
which shows the version of npm installed e.g. 6.4.1. We will revisit npm later
in this book.
Creating our First Server
We will create our first server to better understand how a request and respond
between a client and a server works.
In a code editor of your choice, (I will be using Visual Studio Code in this
book), choose a directory location and in it, create a new file called index.js.
Fill in the below code to create our first server:
const http = require(‘http’)
const server = http.createServer((req, res) =>{
console.log(req.url)
res.end(‘Hello Node.js’)
})
server.listen(3000)
Code Explanation
const http = require(‘http’)
The require function in Node.js helps us to grab the package in Node.js
called http. require is similar to import or include in other languages. require
takes the name of a package as a string argument and returns the package.
We require the http package and assign it to a variable called http. You can
then use http as you would any object. The general convention is that when
you require a module, you put it in a variable that has the same name as the
module itself. In our example, we put the http module in a variable of the
same name http. You can of course choose to put it in a variable with a
different name, there ’ s nothing enforcing that in code, but it does prevent
confusion.
http is one of the built-in packages that Node.js provides to perform actions
on the server. Other essential built-in packages that we will cover later is the
filesystem access (fs) package and the utility function (util) package.
const server = http.createServer(…)
Next, we create and start a server with the createServer method from http
package. createServer takes in a function as parameter:
const server = http.createServer((req, res) =>{
console.log(req.url)
res.end(‘Hello Node.js’)
})
The function provided to createServer is called a callback function. It will be
called when the createServer function is completed. When it is called, it will
be provided the request (req – request from browser) and response (res –
response to give back to browser) object in the function. We can do whatever
we want with the two objects in the body of the function. In our case, we
simply log the request url and after that respond with the text ‘ Hello
Node.js ’ in the function body.
server.listen(3000)
Finally, with server.listen(3000) we start our server to start taking requests. That
is, the server listens on port 3000 for requests. You can specify any port you
want, it doesn ’ t have to be 3000. If you are asking what is a port? A port is a
specific gateway on the server to host a particular app. For example, if there
are multiple apps running on the same server, we specify different port
numbers for different apps.
Running index.js
In our case, for any request made to port 3000, we respond with ‘ Hello
Node.js ’ . To execute the file and start running the server, in Terminal, cd to
the directory the file is located in and run:
node index.js
Now go to your browser and enter http://localhost:3000/. localhost in this
case refers to our computer which is acting as a local server. But suppose the
server is hosted on another computer or site, you can imagine that the link
would be http://:3000/. In the last chapter of this book, we will
learn how to deploy our app on to an external server Heroku to make our app
available across the Internet.
In your browser, you should see the text ‘ Hello Node.js ’ displayed in your
browser (fig. 1.5).
Figure 1.5
This is because we have responded to the request with the code res.end(‘Hello
Node.js’).
If you look at your Terminal running Node.js, you can see ‘ / ’ being logged.
This is because we have the code console.log(req.url) which logs the request url.
If you enter http://localhost:3000/noderocks, ‘ /noderocks ’ will be logged in
the Terminal. So, you see that the req object contains request data from the
browser.
We now have a successful request and respond cycle and I hope that this
serves as an example to better understand how a request and respond works
between a client and a server.
More on Request and Response
Our app currently responds only with ‘ Hello Node.js ’ regardless of the url
entered after localhost:3000. To have different responses based on different
URLs, add the following code in bold:
const http = require(‘http’)
const server = http.createServer((req, res) =>{
if(req.url === ‘/about’)
res.end(‘The about page’)
else if(req.url === ‘/contact’)
res.end(‘The contact page’)
else if(req.url === ‘/’)
res.end(‘The home page’)
else {
res.writeHead(404)
res.end(‘page not found’)
}
})
server.listen(3000)
To run the newly added code, we have to stop and restart the server with
node index.js.
Code Explanation
Using an if-else statement in the callback function, we check for the request
url and depending on its path, we response with different messages. If the url
contains ‘ /about ’ , we serve the about page. If it contains ‘ /contact ’ , we
serve the contact page and if it ’ s just ‘ / ’ , we serve the home page. If the
path does not exist in the if-else, we default to the last else clause and respond
with ‘ page not found ’ and also writeHead(404).
writeHead writes the status code of the request. Normally, a status code of
200 indicates that the server responded with a successful response. You can
see the status code of your request whenever you request a site from the
Chrome browser by going to ‘ Developer Tools under ‘ View ’ ,
‘ Developer ’ , ‘ Developer Tools ’ (fig. 1.6).
Figure 1.6
To see your request information, in ‘ Developer Tools ’ , click on
‘ Network ’ . Under ‘ Status ’ , it will show the status code. In figure 1.7, I
have requested for ‘ /contact ’ url, a valid path which returns status code 200
indication ‘ OK ’ .
Figure 1.7
If I request for an invalid url like ‘ /contacts ’ (with an extra ‘ s ’ ), it returns
the code 404 indicating ‘ Not Found ’ (fig. 1.8).
Figure 1.8
With this, we have a way of handling different requests from a client and
sending the appropriate response from the server.
Responding with HTML
We have been responding to requests with static text. In a real-world setting,
we want to respond with HTML. We illustrate how to do so in this section.
In the same folder as index.js, create a new file called index.html with the
below simple HTML: Home Page
Do the same for about.html( About Page ), contact.html( Contact
Page ) and notfound.html( Page Not Found ).
Back in index.js, add the below code in bold:
const http = require(‘http’)
const fs = require(‘fs’)
const homePage = fs.readFileSync(‘index.html’)
const aboutPage = fs.readFileSync(‘about.html’)
const contactPage = fs.readFileSync(‘contact.html’)
const notFoundPage = fs.readFileSync(‘notfound.html’)
const server = http.createServer((req, res) =>{
if(req.url === ‘/about’)
res.end(aboutPage)
else if(req.url === ‘/contact’)
res.end(contactPage)
else if(req.url === ‘/’)
res.end(homePage)
else {
res.writeHead(404)
res.end(notFoundPage)
}
})
server.listen(3000)
Code Explanation
const fs = require(‘fs’)
We import a file system module ‘ fs ’ which helps us interact with files on
our server.
const homePage = fs.readFileSync(‘index.html’)
const aboutPage = fs.readFileSync(‘about.html’)
const contactPage = fs.readFileSync(‘contact.html’)
const notFoundPage = fs.readFileSync(‘notfound.html’)
The readFileSync method from fs reads the content of each file and returns it.
We store the content in a variable for each page.
const server = http.createServer((req, res) =>{
if(req.url === ‘/about’)
res.end(aboutPage)
else if(req.url === ‘/contact’)
res.end(contactPage)
else if(req.url === ‘/’)
res.end(homePage)
else {
res.writeHead(404)
res.end(notFoundPage)
}
})
Instead of res.end() containing a static text, res.end now contains the HTML
page variable.
Running your App
Re-start the server with node index.js and we will have HTML presented
instead (fig. 1.9). And that is how we respond to requests with HTML using
the filesystem module.
Figure 1.9
Notice that we have been writing a single JavaScript function for our entire
application:

const server = http.createServer((req, res) =>{
if(req.url === ‘/about’)
res.end(aboutPage)
else if(req.url === ‘/contact’)
res.end(contactPage)
else if(req.url === ‘/’)
res.end(homePage)
else {
res.writeHead(404)
res.end(notFoundPage)
}
})

This single function listens to a web browser ’ s requests, either from a
computer. mobile phone or any other client consuming our API. We call this
function a request handler. When a request comes in, this function looks at
the request and decides how to respond. It takes two arguments, an object that
represents the request (req) and an object that represents the response (res).
Every Node.js application is just like this, a single request handler function
responding to requests. For small sites, this might seem easy, but things
quickly get huge and unmanageable quickly as you can imagine, for example
a site like Amazon.com which includes rendering dynamic reusable HTML
templates, rendering/uploading of images etc. We explore in the next chapter
how Express helps to solve this problem and make it easier for us to write
web applications with Node.js.
Summary
In this book, we will build a blog app with Node.js, Express and MongoDB.
Node.js allow us to use JavaScript as a server-side programming language
which gives us advantages like fast execution and being able to share code
between the server and client. We understood how a request and respond
cycle between a client and server works by coding and starting up a simple
server example. We handled requests and responded appropriately with both
text and HTML.
CHAPTER 2: INTRODUCTION TO NPM &
EXPRESS
Installing Custom Packages with npm
In our app from chapter one, we imported packages from Node.js itself e.g.,
http, fs. Now the Node.js community have lots of developers who write
custom modules/packages that we can use in our own apps. These packages
are hosted on a site called npmjs.com (fig. 2.1) where you can search to see
which is appropriate to use in your own code. We use npm (or Node Package
Manager) to manage the packages that we download. npm is an official
helper for Node projects that comes along with Node when we installed it.
Figure 2.1
One very important custom package we will install is Express. Because
vanilla Node.js APIs can be verbose, confusing and limited in features,
Express is a framework that acts as a light layer atop the Node.js web server
making it easier to develop Node.js web applications. Express is used by
many companies. We will see later how it simplifies the APIs of Node.js,
adds helpful features, helps organizes our application ’ s functionality with
middleware and routing, adds helpful utilities to Node.js ’ s HTTP objects
and facilitates rendering of dynamic HTML views. In the course of this book,
we will explore these features in depth.
So, go to npmjs.com and search for ‘ express ’ , there will be instructions on
how to install and use the express package (fig. 2.2).
Figure 2.2
As mentioned in the site under ‘ Installation ’ , we have to run npm install
express to install the express package.
Before we run npm install express, npm requires that we have a file
package.json to track all packages and their versions used in our app. If you
run npm install express now without the file, you will get a series of warnings
like “ no such file or directory, open … package.json ” .
To generate package.json file, run ‘ npm init ’ which will prompt a series of
questions about our project (e.g. project name, author, version) to create
package.json for us. You can of course manually create package.json on your
own. But npm init saves us a bit of time when creating package.json files. For
now, just press enter for all the questions and at the end, package.json (with
the contents something like the below) will have been generated for us.
{
“name”: “node”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″
},
“author”: “”,
“license”: “ISC”
}
As you can see, package.json contains metadata about our Node project like
the name of the project, its version and its authors.
Next, proceed to install ‘ express ’ with npm install express. When
installation of express is finished, you will notice that a new property
dependencies has been added to package.json.
{
“name”: “node”,
“version”: “1.0.0”,
“description”: “”,
“main”: “index.js”,
“scripts”: {
“test”: “echo \”Error: no test specified\” && exit 1″
},
“author”: “”,
“license”: “ISC”,
“dependencies”: {
“express”: “^4.16.4”
}
}
Dependencies contain the dependency packages and their version numbers.
For now, we have Express version 4.16.4 (at time of book ’ s writing). Each
time we install a package, npm saves it here to keep track of the packages
used in our app.
npm install express installs the express package into our app by fetching the
latest version of Express and putting it in a folder called node_modules. If
you look at your app folder, the node_modules folder will have been created
for you (fig. 2.3). This is where custom dependencies are saved for our
project.
Figure 2.3
If you open and explore node_modules, you should be able to locate the
express package. The reason why we see many other packages in
node_modules even though we only installed express is because express
depends on these other packages and they were installed when express was
installed. These other packages are dependencies of Express. The file
package-lock.json tracks the versions of all the dependencies of Express.
Introduction to Express
In this section, we introduce Express and how it makes application
development in Node easier and faster. First, we import express into our app
by adding the below code to index.js:
const express = require(‘express’)
This pulls in the package from the node_modules directory.
To appreciate how much easier Express makes development for us, we are
going to use Express to repeat what we have previously done in chapter one.
Previously, we created a server and started it with:
const http = require(‘http’)
const server = http.createServer((req, res) =>{

})
server.listen(3000)
That is, we have to take care of importing http, fs, other packages, and also
the request and response object. But with Express, we achieve the same with:
const express = require(‘express’) // require express module
const app = express() // calls express function to start new Express app
app.listen(3000,()=>{
console.log(“App listening on port 3000”)
})
Express takes care of the http, request and response objects behind the
scenes. The callback function provided in the 2nd argument in app.listen() is
executed when the servers starts listening.
Running your App
Copy the above Express code into index.js, run node index.js in the command
and see the log “ App listening on port 3000 ” printed. We will read more about the
advantages of using Express in the next section.
Handing Requests with Express
Express allows greater flexibility in responding to browser ‘ get ’ or ‘ post ’
requests. We illustrate this in the following code in bold:
const express = require(‘express’)
const app = express()
app.listen(3000,()=>{
console.log(“App listening on port 3000”)
})
app.get(‘/’,(req,res)=>{
res.json({
name: ‘Greg Lim’
})
})
In the above code, you can see that Express has populated more operations
for us to respond better to browser requests. For example, we return a JSON
respond back to the browser with res.json. This thus lets us build APIs with
Node. We can define specific routes and its response our server gives when a
route is hit, for example:
app.get(‘/about’,(req,res)=>{
res.json({
name: ‘Greg Lim’
})
})
This is also called Routing where we map requests to specific handlers
depending on their URL. Previously without Express, we had to respond to
individual routes with an extended if-else statement in one big request
handler:
const server = http.createServer((req, res) =>{
if(req.url === ‘/about’)
res.end(aboutPage)
else if(req.url === ‘/contact’)
res.end(contactPage)
else if(req.url === ‘/’)
res.end(homePage)
else {
res.writeHead(404)
res.end(notFoundPage)
}
})
With Express, we can refactor one big request handler function into many
smaller request handlers that each handle a specific function. This allow us to
build our app in a more modular and maintainable way.
We can also define the type of response the server serves. For example, to
serve HTML files with express, we add the following:
const path = require(‘path’)

app.get(‘/’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’index.html’))
})
Code Explanation
const path = require(‘path’)
We introduce a new module called path. path is another built in module in
Node. It helps us get the specific path to this file, because if we do
res.sendFile( ‘ index.html ’ ), there will be error thrown as an absolute path is
needed.
path.resolve(__dirname,’index.html’) helps us get the full absolute path which
otherwise changes based on different Operating Systems. For example, on
Mac and Linux, we refer to a directory using /directory, but on Windows, we
refer to it using \directory. The path module ensures that things run smoothly
regardless if the OS is Windows, Mac or Linux.
app.get(‘/’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’index.html’))
})
Express also adds things like the sendFile method which if we had to
implement without Express, would be about 45 lines of complicated file
code. Thus, I hope you come to slowly appreciate how Express makes it
easier to write these request handler functions and in general simplify
development in Node.
Asynchronous with Call Back Functions
We have been seeing a few examples of code with callback functions.
Callback functions are an important aspect in Node.js that help support tasks
to be done asynchronously. That is, rather than waiting for one task to
complete before executing another e.g. in PHP:
Task 1 -> Task 2 -> Task 3 -> Task 4 -> Completion
Node.js allows the possibility to performs tasks in parallel, where no task is
blocking another.
Task 1 ->
Task 2 ->
Task 3 ->
Task 4 ->
How Node.js supports asynchronous code is with callback functions. For
example, the below request handlers do not have to be executed
synchronously.
app.get(‘/’,(req,res)=>{
// query database
})
app.get(‘/about’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’about.html’))
})
That is, if a request for ‘ / ’ and ‘ /about ’ comes in together, it doesn ’ t have
to be the case that one request has to be completed before serving the other.
Both tasks can begin at the same time. It can be that the task to query the
database starts and while the database is thinking, the second request for
‘ about.html ’ can be responded. Our code is not doing two things at once, but
when a task is waiting on something, the other task can execute.
Asynchronous code like callback functions thus execute much faster.
Serving Other HTML files
To serve the about and contact HTML files, add the following:
app.get(‘/about’,(req,res)=>{ // called when request to /about comes in
res.sendFile(path.resolve(__dirname,’about.html’))
})
app.get(‘/contact’,(req,res)=>{ //called when request to /contact comes
res.sendFile(path.resolve(__dirname,’contact.html’))
})
If you restart the server, our app will serve the about file when a request to
/about comes in and serve the contact file when a request to /contact comes
in.
Note here that we use app.get to handle HTTP GET requests which are the
most common HTTP method. GET request as its name suggest gets resources
like a homepage, an image etc. GET methods do not change the state of our
app, it simply retrieves. Other methods like POST and PUT do that and we
will cover them in the course of this book.
Serving Static Files with Express
Now that we are serving HTML pages from our server, how do we include
static files like fonts, images and CSS with Express?
To do so, in index.js add the line in bold:
const express = require(‘express’)
const app = express()
const path = require(‘path’)
app.use(express.static(‘public’))
app.listen(3000,()=>{
console.log(“App listening on port 3000″)
})
app.use is a special function to increase functionality with Express by adding
a function to our application ’ s middleware stack. We will discuss more on
middleware in a dedicated chapter later on.
express.static is a packaged shipped with Express that helps us serve static
files. With express.static( ‘ public ’ ), we specify that any request that ask for
assets should get it from the ‘ public ’ directory.
To illustrate this, first create a folder called ‘ public ’ in our app folder. In it,
create the sub-folders ‘ css ’ and ‘ js ’ (fig. 2.3). We will be referencing
these two folders from our index.html file.
Figure 2.3
Referencing index.css
In the ‘ css ’ folder, create a file called index.css with the following code:
body {
background-color: coral;
}
To reference index.css in index.html, add in index.html the following line:
Home Page
Note that when we reference href=”css/index.css”, Express refers to
/public/css/index.css. That is, the url for the static file being served is
determined by combining its url with ‘ public ’ .
Referencing index.js
To link to an external js file, we similarly add the below to index.html:
This assumes that there is a sub folder in public called js containing the file
index.js.
Important note: the index.js that index.html refers to in this case is for the
client side, not the server side index.js!
Summary
We learnt how to install third party custom packages using npm. A core
custom package is Express which helps make it easier to handle requests and
serve responses, thus making app development in Node easier in general. We
generated the package.json file that maintains our project metadata
particularly its dependencies in an organized manner. We also learnt how to
serve static files to make CSS and JavaScript files available to the HTML
client files.
CHAPTER 3: BEGINNING OUR BLOG
PROJECT
Downloading the Blog Template
As this book is not about website design, CSS or how to come up with a
graphical user interface, we will use a blog template to start off our project.
We will be using the ‘ Clean Blog ’ theme from startbootstrap.com
(https://startbootstrap.com/themes/clean-blog/ fig. 3.1).
Figure 3.1
Download the .zip file that contains the theme and extract it to a new folder
for this project.
Go to Terminal and cd to the new folder. Run npm init and say ‘ yes ’ to all
the questions for package.json to be generated for us.
Next in the folder, install Express with:
npm install express
In that folder, create index.js which will serve as the root of the project. Fill it
with the following code:
const express = require(‘express’)
const app = new express()
app.listen(4000, ()=>{
console.log(‘App listening on port 4000’)
})
As covered earlier, start the server by running node index.js in Terminal.
Automatic Server Restart with nodemon
For now, we have been starting and stopping our server each time we make a
code change in index.js. Now, we will install a package called nodemon that
automatically detects code changes and restart the server so we don ’ t have
to manually stop and restart it. Install nodemon with the following command:
npm install nodemon –save-dev
The –save option is to have the dependencies listed in our package.json so
that someone else can install the dependencies later if we give them the
project – they need only to run npm install with no arguments. You can also
manually edit package.json and then run npm install to add dependencies.
Without the –save option, we would have the node_modules folder but it will
not be reflected in our package.json.
The -dev option is to specify that we install nodemon for development
purposes only. We do not want nodemon to be part of the production version
of the app. When nodemon is installed, in package.json you can see it listed
under devDependencies. This indicates that the package is for development
purposes only and not included in our app when we deploy it.
npm start
We will be starting our app from within a npm script with npm start. To do
so, in package.json, go to “ scripts ” and make the following change:

“scripts”: {
“start”: “nodemon index.js”
},

So instead of running our app with node index.js as we have done previously,
we now run it with: npm start. npm start looks inside our package.json file,
see that we have added a script called start, and run the associated command
i.e. nodemon index.js. nodemon watches our files for changes and
automatically restarts the server when there are code changes.
We can of course just run nodemon index.js directly, but because npm start is
a convention where most Node web servers can be started with npm start.
That is to say, we don ’ t have to know the actual file name whether index.js
or app.js, we just start the server with npm start.
Also, npm start allows you to run more complex command(s) when your app
grows e.g. starting database server or clearing log files before starting up the
server. Now, make sure that the server is running with npm start.
public folder for serving static files
Next, we will register a public folder for our static files as what we have done
in the previous chapter. In index.js, add the following:
const express = require(‘express’)
const app = new express()
app.use(express.static(‘public’))
app.listen(4000, ()=>{
console.log(‘App listening on port 4000’)
})
With this, Express will expect all static assets to be in the public directory.
Thus, proceed to create a new folder called public in the app directory. Move
the following files from the downloaded template files into public:
index.html
about.html
contact.html
post.html
Next, move the following downloaded template folders into public:
css
img
js
vendor
If you are wondering how to know which files and folders to move to public,
look inside index.html and see which static assets it is referencing. I go
through the relevant pieces of index.html below:
In the head tag index.html, we can see that it is referencing folders vendor and
css.

Clean Blog – Start Bootstrap Theme

In body, under the navigation bar, we see that it refers to index.html,
about.html, post.html and contact.html. These therefore are to be in public
root.

Home
About
Sample Post
Contact
Towards the end of the file, vendor is again referenced. js is also referenced.
And that is why we move index.html, about.html, contact.html, post.html
template files and css, img, js, vendor template folders into public:
Now if you go to localhost:4000, Express should serve your index.html along
with its static assets (fig. 3.1).
Figure 3.1
And if you click the about, sample post and contact links, it should navigate
to those pages as well.
Creating Page Routes
Currently, we are serving index.html, about.html, post.html and contact.html
from the public folder, which is treating it like any other static file. We
should however be serving these files by defining specific routes with app.get
and responding when specific routes are hit as what we have done before. To
do so, create a pages folder in the root app directory and move all the HTML
files from public over there.
After copying the files, we will setup the routes for the various pages. To
setup the homepage route, we register a get route to serve the home HTML
when we receive a request from the browser. Add the following in index.js:
const express = require(‘express’)
const path = require(‘path’)
const app = new express()

app.get(‘/’,(req,res)=>{
res.sendFile(path.resolve(__dirname, ‘pages/index.html’))
})
Now when a request is made to the home page route ‘ / ’ , index.html will be
served.
Try it Yourself
Can you try creating the about, sample post and contact page routes on your
own? The route code should be similar to what we have created for our home
page route. So, take some time and try it on your own. Else, you can follow
my solution below.
In index.js, create the new route for about, contact and sample by adding the
below:
app.get(‘/about’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’pages/about.html’))
})
app.get(‘/contact’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’pages/contact.html’))
})
app.get(‘/post’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’pages/post.html’))
})
Do note that we have to append ‘ pages/ ’ before the html file because we are
storing the HTML files in the pages folder.
Links in index.html
Now if you run your app and try to navigate to about, contact and sample
post pages from the nav bar, you will realize that they don ’ t work or get a
“ Cannot GET /contact.html ” error. This is because in index.html, we
currently refer to other pages with href links to the actual html files i.e.
about.html as shown below:
Home
About
Sample Post
Contact
Because we have already moved them away from the public folder, they
can ’ t be found. Instead we have to use the routes that we defined earlier to
navigate to those pages. That is, in index.html, replace the href links with the
below routes:
Home
About
Sample Post
Contact
We have to repeat the above link change for the nav bar in about.html,
contact.html and post.html as well, else the links will still break. You will
quickly realize that this is tedious, repetitive work. What if we have to add a
new link to our nav bar? That means we have to repeat the same code for the
nav bar in all of our pages. You will realize that this is very unnecessary
duplicative work! It is not scalable and it becomes increasingly difficult as
our app grows.
In this next section, we will resolve this problem by using templating
engines.
Summary
We began our blog project with an existing blog template from
startbootstrap.com and incorporated it into a Node.js project. Using the
nodemon package, we automatically detect code changes in our project and
restart the server. Page routes were created to serve the home, about and post
pages. A navigation bar was created to contain the links to these routes.
Refer to https://github.com/greglim81/express_chap3-8 for the source code of
this chapter. If you face any issues, contact me at support@i-ducate.com
CHAPTER 4: TEMPLATING ENGINES
Templating engines help us dynamically render HTML pages in contrast to
just having fixed static pages which in the earlier chapter gives us a problem
that we have to duplicate the nav bar code for all static pages. In this chapter,
we will refactor our app to use a templating engine that allows us to abstract
our app into different layout files so that we don ’ t repeat common code, yet
still serve the same HTML file as before.
There are many templating engines out there like Handlebars, Pug, and more.
But we will use ‘ EJS ’ (which stands for Embedded JavaScript) because it is
one of the more popular templating engines and is made by the people who
created Express. All these different templating engines at the end of the day
have the same purpose which is to output HTML.
As stated on its site, EJS is a simple templating language that lets us generate
HTML with plain JavaScript in simple straightforward scriplet tags i.e. .
First, install EJS with npm:
npm install ejs –save
To use EJS in our app, in index.js add the following:
const express = require(‘express’)
const path = require(‘path’)
const app = new express()
const ejs = require(‘ejs’)
app.set(‘view engine’,’ejs’)
With app.set(‘view engine’,’ejs’), we tell Express to use EJS as our templating
engine, that any file ending in .ejs should be rendered with the EJS package.
Previously, we responded to a get request with the following:
app.get(‘/’,(req,res)=>{
res.sendFile(path.resolve(__dirname,’pages/index.html’))
})
Now with EJS, we do the following,
app.get(‘/’,(req,res)=>{
res.render(‘index’);
})
We send a view to the user by using res.render(). Express adds the render
method to the response object. res.render( ‘ index ’ ) will look in a ‘views’
folder for the file index.ejs. Thus, we rename our current pages folder to
views. And in it, rename the file extension of index.html to index.ejs.
We also change the get request handlers with res.render for about, contact
and post routes:
app.get(‘/about’,(req,res)=>{
//res.sendFile(path.resolve(__dirname,’pages/about.html’))
res.render(‘about’);
})
app.get(‘/contact’,(req,res)=>{
//res.sendFile(path.resolve(__dirname,’pages/contact.html’))
res.render(‘contact’);
})
app.get(‘/post’,(req,res)=>{
//res.sendFile(path.resolve(__dirname,’pages/post.html’))
res.render(‘post’)
})
Thus, change the file extensions of about.html, contact.html, and post.html to
about.ejs, contact.ejs and post.ejs. In all, we should now have a views folder
with the following EJS files (fig. 4.1).
Figure 4.1
Layouts
To solve the problem of repetitive code (e.g. nav bar, footer) appearing in
each page, we will use the concept of a layout file. A layout file contains
everything common in a page, for e.g., navbar layout, header layout, footer
layout, scripts layout. Each page will then include these layout files in
additional to their own content. This results in a much concise, readable and
manageable file.
In index.ejs, notice the repeating elements that is, the , ,
and elements that also appear in the other views. Our aim
is to extract these portion of common HTML code into their own separate
layout files i.e. header.ejs, navbar.ejs, footer.ejs and scripts.ejs. We then just
include the files that need them instead of repeating the entire code thus
reducing much code clutter.
First, create a sub folder in views called layouts to store these files.
Next, extract the HTML into header.ejs as shown below:
Clean Blog – Start Bootstrap Theme
Next, extract the HTML into layout file navbar.ejs:
Start Bootstrap
Menu
Home
About
Sample Post
Contact
Extract the HTML into layout file footer.ejs:
Copyright © Your Website 2019
And finally extract the elements into scripts.ejs.
Having extracted header, nav, footer and scripts into the various layout files,
index.ejs now include the various layout files in place of the extracted code as
shown:
Clean Blog
A Blog Theme by Start Bootstrap

Code Explanation
The include call receives a path relative to the template. So, since the path of
header.ejs is in ./views/layouts/header.ejs and index.ejs is in ./views/index.ejs,
we specify include(‘layouts/header’).
We use the raw output tag {
console.log(error,blogpost)
})
Code Explanation
const BlogPost = require(‘./models/BlogPost’)
We import the BlogPost model we just created by specifying its relative path.
BlogPost represents the BlogPosts collection in the database.
mongoose.connect(‘mongodb://localhost/my_database’, {useNewUrlParser: true});
We then proceed to connect to the database. Remember that if my_database
doesn’t exist, it will be created for us.
BlogPost.create({
title: ‘The Mythbuster’s Guide to Saving Money on Energy Bills’,
body: ‘If you have been here a long time, you might remember when I went on ITV Tonight to
dispense a masterclass in saving money on energy bills. Energy-saving is one of my favourite money
topics…’
}, (error, blogpost) =>{
console.log(error, blogpost)
})
We then create a new BlogPost document in our database with a function in
BlogPost called create. In the first argument, we pass in the data for the
blogpost document. In the 2nd argument, we pass in a call back function
which is called when create finishes execution. Mongoose gives us any error
in the error argument if there was any during the create operation. It also
return us the newly created post in the blogpost argument.
To execute test.js, run node test.js in the Terminal. You should see null
(error) and the blogpost object being logged like the below:
null { _id: 5cb436980b33147489eadfbb,
title: ‘The Mythbuster’s Guide to Saving Money on Energy Bills’,
body:
‘If you have been here a long time, you might remember when I went on ITV Tonight to dispense a
masterclass in saving money on energy bills. Energy-saving is one of my favourite money topics,
because once you get past the boring bullet-point lists, a whole new world of thrifty nerdery opens up.
You know those bullet-point lists. You start spotting them everything at this time of year. They go like
this:’,
__v: 0 }
Notice that there is an additional field _id. _id is a unique id provided by
MongoDB for every document.
Visualizing Data in MongoDB
To see the data visually in MongoDB, open up MongoDB Compass and you
should see my_database on the left panel (fig. 5.1). Under it, you should see
the collection blogposts.
Figure 5.1
And if you click on blogposts, you will be able to see the blogpost document
that we have just created (fig. 5.2). Try inserting more blog posts and see
them reflected in MongoDB.
Figure 5.2
Reading Data from MongoDB using Mongoose
To select all documents in BlogPosts collection: pass an empty document as
the query filter parameter to the first argument of the find method.
BlogPost.find({}, (error, blogspot) =>{
console.log(error,blogspot)
})
The query filter parameter determines the select criteria. Thus, to find all
documents in BlogPosts collection with a particular title for e.g. ‘The
Mythbuster’s Guide to Saving Money on Energy Bills’ , we do:
BlogPost.find({
title:’The Mythbuster’s Guide to Saving Money on Energy Bills’
}, (error, blogspot) =>{
console.log(error,blogspot)
})
Or, to find all documents in BlogPosts collection with ‘ The ’ in the title, we
do:
BlogPost.find({
title:/The/}, (error, blogspot) =>{
console.log(error,blogspot)
})
That is, we place the wildcard operator before and after The. For those
familiar with SQL, ‘ / ’ acts like ‘ % ’ .
To get single database documents, i.e. to retrieve single documents with
unique id _id, we use the findById method:
var id = “5cb436980b33147489eadfbb”;
BlogPost.findById(id, (error, blogspot) =>{
console.log(error,blogspot)
})
There are many other search constraints conditions you can apply to find.
Refer to https://docs.mongodb.com/manual/tutorial/query-documents/ for
more information.
Updating Records
To update a record, we use findByIdAndUpdate where we provide id as the
first argument and the fields/values to be updated in the second argument.
var id = “5cb436980b33147489eadfbb”;
BlogPost.findByIdAndUpdate(id,{
title:’Updated title’
}, (error, blogspot) =>{
console.log(error,blogspot)
})
Deleting Single Record
To delete a record, we use the findByIdAndDelete where we provide id as the
first argument.
var id = “5cb436980b33147489eadfbb”;
BlogPost.findByIdAndDelete(id, (error, blogspot) =>{
console.log(error,blogspot)
})
Summary
We were introduced to MongoDB, a NoSQL database that stores data in the
form of collections and documents. Using Mongoose, we connected our
Node application with the Mongo database. We defined models using the
schema interface to represent the collections in our database. We illustrated
Create, Read, Update and Delete operations via Mongoose. Finally, we used
MongoDB Compass to see the stored data visually in MongoDB.
Refer to https://github.com/greglim81/express_chap3-8 for the source code of
this chapter. If you face any issues, contact me at support@i-ducate.com
CHAPTER 6: APPLYING MONGODB TO
OUR PROJECT
Having introduced MongoDB, we now use MongoDB database to build our
app. First, we will implement the functionality for users to create a new post.
For that, we will need a view for users to input the data.
In the views folder, create a new file create.ejs. As a starting point, copy the
code from contact.ejs into create.ejs. That is, create.ejs like the other views
will include the header, navbar, footer and scripts. But change the text
to ‘ Create New Post ’ :
Next, register the route for ‘ Create New Post ’ by appending the below to
index.js:
app.get(‘/posts/new’,(req,res)=>{
res.render(‘create’)
}
Next, add the ‘ New Post ’ in the nav bar. In views/layouts/navbar.ejs, add
the following:
Home
About
Sample Post
Contact
New Post
Now if you run your app and go to your ‘ New Post ’ view, the page should
appear but it seems that it could not reference the static files like css, images,
js and vendor folders (fig. 6.1).
Figure 6.1
This is because our page is a two-level route and can ’ t reference the
required static files for e.g. in header.ejs, because the href is:
It cannot find a vendor folder at its sub level. To rectify this, we need href to
point to an absolute reference by simply adding a ‘ / ’ before it:
Thus, go back to header.ejs, scripts.ejs and create.ejs to make sure that hrefs
are absolute references. i.e. in header.ejs:

Super Clean Blog – Start Bootstrap Theme

In scripts.ejs:
In create.ejs:


With this, two level (and further levels) routes can have absolute references
to our static assets.
Now if you run your app, and go to your ‘ New Post ’ view, the page should
appear fine as it is able to reference the static files like css, images, js and
vendor folders.
In create.ejs, there is already an existing form from contact.ejs. In place of
name, we change it to title (blog title). Because we do not need the email and
phone number fields, remove it. And rename ‘ Message ’ to body (blog
content body).
For simplicity ’ s sake, we have also removed certain form validation
elements like required data-validation-required-message=”Please enter a
message.” and alert messages () as
we want to focus on getting our form right. We will later come back to form
validation and presenting alert messages. The create form should look
something like:

// bootstrap classes
Title
Description
Send

Note that you need the name attribute for each field i.e.
Else, the data won ’ t be passed from the form to the server.
Also note that in:
It means that when the form is submitted, the browser will make a ‘ POST ’
request to the /posts/store end point. A ‘ POST ’ request is needed to pass
form data from the browser to our Node.js app to create the record in the
database.
In index.js add the following function to handle the POST request:
app.post(‘/posts/store’,(req,res)=>{
console.log(req.body)
res.redirect(‘/’)
})
In the function, we get the form data from the browser via the request body
attribute. But to enable this, we first need to install the body parsing
middleware called body-parser. body-parser parse incoming request bodies
in a middleware and make the form data available under the req.body
property.
Here, we handle a POST request which is generally used to request an
addition to the state of the server unlike GET where we simply get resources.
A user POSTs a blog entry, a photo, signing up for an account, buying an
item etc. POST is used to create records on servers. For modifying existing
records, we use the PUT request.
So, proceed to install body-parser using:
npm install body-parser
Then add the following into index.js:

const bodyParser = require(‘body-parser’)
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:true}))

Running our App
If you run your app now, go to ‘ New Post ’ and fill in the form and hit
submit. You will be redirected to the home page with the response ’ s redirect
method (Express adds the redirect method to the response object for us –
using just Node, redirecting will need a lot more code). In the console log,
you will see your entered values in an object e.g.:
{ title: ‘title1’, body: ‘body1’ }
This is thus how we can retrieve data entered into a form. With bodyParser, a
new body object containing the parsed data is populated on the request
object. You can access individual properties in the body object i.e.
req.body.title, req.body.body.
Saving Posts to the Database
Having the browser form data in req.body, we now use it with the BlogPost
model to create a new document in the BlogPosts collection, or in other
words, have our data stored in the database. Add the following in index.js:

const BlogPost = require(‘./models/BlogPost.js’)

app.post(‘/posts/store’,(req,res)=>{
// model creates a new doc with browser data
BlogPost.create(req.body,(error,blogpost) =>{
res.redirect(‘/’)
})
})
We import the BlogPost model, call its create method, provide req.body as
first argument and a callback function as the 2nd argument which is called
when create completes.
If you run your app, fill in data into the form and hit submit. You can see
your newly created blogpost data in the BlogPosts collection (fig. 6.2).
Figure 6.2
You might notice that our code for creating a blog post becomes slightly
more complex in that we have a callback function in a callback function.
When our app grows and we make more asynchronous method calls, it might
be the case that we might have more callback layers. This is what we often
refer to as ‘ callback hell ’ , where the nested callback code is difficult to
understand.
app.post(‘/posts/store’,(req,res)=>{
// model creates a new doc with browser data
BlogPost.create(req.body,(error,blogpost) =>{
res.redirect(‘/’)
})
})
To resolve this, we can alternatively use a feature in ES8 called async and
await for asynchronous method calling as shown in the following code:
app.post(‘/posts/store’, async (req,res)=>{
await BlogPost.create(req.body)
res.redirect(‘/’)
})
With async, we specify that the following method is an asynchronous call.
And using await for BlogPost.create, we are saying that we will await the
completion of the current line before the below line can be executed. This
thus lets us have more readable code.
Displaying a List of Blog Posts
To display the list of blog posts, we use the BlogPost model ’ s find method
(we have previously went through find in the “ Introduction to MongoDB ”
chapter) to find all the database records. We do this whenever the home page
is requested. Thus in app.get for the home page i.e. ‘ / ’ , we do:
app.get(‘/’,async (req,res)=>{
const blogposts = await BlogPost.find({})
res.render(‘index’,{
blogposts: blogposts
});
})
Having retrieved all the blog posts and assigning them to the variable
blogposts, we pass back the blogposts data back to the client browser by
providing it as the 2nd argument to render. And whenever the key name and
value name are the same (e.g. blogposts: blogposts), we can shorten it to
simply:
app.get(‘/’,async (req,res)=>{
const blogposts = await BlogPost.find({})
res.render(‘index’,{
blogposts
});
})
With this, index.ejs view now has access to the blogposts variable.
Because we console log blogposts with console.log(blogposts), we can see
that blogposts is an array of BlogPost objects.
[ { _id: 5cb836f610d8d629530fcf82,
title: ‘title2’,
body: ‘desc2’,
__v: 0 },
{ _id: 5cb8371810d8d629530fcf83,
title: ‘title3’,
body: ‘desc3’,
__v: 0 },
{ _id: 5cb839e78e235d2aa29d87e1,
title: ‘title4’,
body: ‘desc4’,
__v: 0 } ]
Dynamic Data with Templating Engines
Now that we have the blogposts data returned in an array, we will use our
EJS templating engine to dynamically display the blog posts in the home
view.
In index.ejs, you currently see repeated tags
each representing a blog post. Thus, we will loop through the blogposts array
in a for loop and render a tag for each blogpost
with the following in bold:


Posted by
Start Bootstrap
on September 24, 2019

Code Explanation
With the provided blogposts array, we use a for loop to loop through its
elements.
Posted by
Start Bootstrap
on September 24, 2019
We then populate the:
– blogpost title under the tag,
– blogpost body under
If you run your app now, you will see the blog posts dynamically displayed
(fig. 6.3).
Figure 6.3
There are of course other fields that we could have populated for each blog
post, for e.g.:
– individual blog post route in ,
– blog post author name in Posted by …
– and blog post date in on September 24, 2019
We will work to populate the blogpost author name and date in later sections
of the book.
For the blogpost route, populate it as:


In the next section we will work to generate single pages for each blog post
route.
Try It Out
Now that we have implemented listing all blog posts in the home page, can
you try as an exercise how to add a search bar and only list blog posts that fit
the search terms?
Previously, we supplied no search criteria to BlogPost.find({}…) to get all the
posts.
BlogPost.find({}, (error, blogspot) =>{
console.log(error,blogspot)
})
Now, can you supply query filter parameters to determine the search criteria?
E.g. to find all documents in BlogPosts collection with a particular title for
e.g. ‘The Mythbuster’s Guide to Saving Money on Energy Bills’ , we do:
BlogPost.find({
title:’The Mythbuster’s Guide to Saving Money on Energy Bills’
}, (error, blogspot) =>{
console.log(error,blogspot)
})
Or, to find all documents in BlogPosts collection with ‘ The ’ in the title, we
do:
BlogPost.find({
title:/The/}, (error, blogspot) =>{
console.log(error,blogspot)
})
Try it out and let me know at support@i-ducate.com if you face issues.
Single Blog Post Page
We want to display each blog post ’ s detail in their own specific url. First we
need to change the route definition for a single blog post. Currently in
index.js, app.get( ‘ /post … is:
app.get(‘/post’,(req,res)=>{
res.render(‘post’)
})
Change it to:
app.get(‘/post/:id’,async (req,res)=>{
const blogpost = await BlogPost.findById(req.params.id)
res.render(‘post’,{
blogpost
})
})
Code Explanation
app.get(‘/post/:id’…
First, we append a parameter to the route for a single post. :id represents a
wild card that accepts any string value, e.g.
http://localhost:4000/post/5cb836f610d8d629530fcf82. In our case, we have
populated id with blogpost _id i.e. .
The parameters after /post/ can be retrieved with req.params. For example, if
we run
app.get(‘/post/:id’,async (req,res)=>{
console.log(req.params)
})
We get the params object being printed out:
{ id: ‘5cb836f610d8d629530fcf82’ }
That is, it prints out the key and value of the param in the route. With the
param id, we use it to call BlogPost.findById which retrieves the specific blog
post with that id and pass the blogpost variable to post.ejs.
app.get(‘/post/:id’,async (req,res)=>{
const blogpost = await BlogPost.findById(req.params.id)
res.render(‘post’,{
blogpost
})
})
post.ejs
To dynamically display each post ’ s unique data in post.ejs, make the
following changes in bold:
Posted by
Start Bootstrap
on August 24, 2019
Code Explanation
To dynamically display each post ’ s unique data, we change the title in the
tag to
,
change subheading in to
and article body to .
Running your App
Now when you run your app and click on a specific post from the Home
view, the Post view will be populated with that specific blog post ’ s data. If
you click on another post, the title and body will dynamically change to that
blog post ’ s data.
Adding Fields to the Schema
Because we currently only have title and body field for our blog post, we
additionally require a username field and a datePosted field to know who and
when the post was created. To add the fields, add in the codes in bold below:
const mongoose = require(‘mongoose’)
const Schema = mongoose.Schema;
const BlogPostSchema = new Schema({
title: String,
body: String,
username: String,
datePosted:{ /* can declare property type with an object like this because we need ‘default’ */
type: Date,
default: new Date()
}
});
const BlogPost = mongoose.model(‘BlogPost’,BlogPostSchema);
module.exports = BlogPost
With the added fields, make changes in index.ejs and post.ejs:
index.ejs

Posted by
on
Older Posts →
post.ejs

Posted by
on

Now delete the records in the database and re-insert the records so that our
blog post contains the additional fields. This time, datePosted will be auto
populated. Later on, we will populate the username field when we implement
the login function.
Summary
We used MongoDB to build our blog app. We implemented a form to create
a blog post and used the body-parser package to retrieve the form field data.
The BlogPost model was used to store the data in the database. We displayed
the list of blog posts in the home page with the EJS templating engine and
also displayed each blog post detail in their own individual pages.
Refer to https://github.com/greglim81/express_chap3-8 for the source code of
this chapter. If you face any issues, contact me at support@i-ducate.com
CHAPTER 7: UPLOADING AN IMAGE WITH
EXPRESS
In this chapter, we will explore how to upload an image for a blog post. We
will install a package express-fileupload to help upload files in Express
(https://www.npmjs.com/package/express-fileupload).
As stated in its docs, run the following to install express-fileupload:
npm install –save express-fileupload
Next, add a file upload field in our create post form (fig. 7.1).
Figure 7.1
In create.ejs, add the following code in bold:

Image
Send
Code Explanation
enctype=”multipart/form-data” is for the browser to know that the form
contains multi media. The browser will then encrypt the multi media before
sending it to the server.
In index.js, in the request handler for ‘ /posts/store ’ , add:

const fileUpload = require(‘express-fileupload’)
app.use(fileUpload())

app.post(‘/posts/store’, (req,res)=>{
let image = req.files.image;
image.mv(path.resolve(__dirname,’public/img’,image.name),async
(error)=>{
await BlogPost.create(req.body)
res.redirect(‘/’)
})
})
Code Explanation
const fileUpload = require(‘express-fileupload’)
adds the files property to the req object so that we can access
the uploaded files using req.files.
express-fileupload
We then register the package in Express with app.use(fileUpload())
app.post(‘/posts/store’, (req,res)=>{
let image = req.files.image;
image.mv(path.resolve(__dirname,’public/img’,image.name),async
(error)=>{
await BlogPost.create(req.body)
res.redirect(‘/’)
})
})
We first create a shortcut to req.files.image with image. The req.files.image
object contains certain properties like mv – a function to move the file
elsewhere on your server and name.
(See https://www.npmjs.com/package/express-fileupload for the complete list
of what it contains.)
image.mv moves the uploaded file to public/img directory with the name
from image.name. When this is done, we proceed to create post as what we
have done before.
Do note the positioning of the async statement. Only in the scope where we
use await should async be declared.
Running your App
When you run your app, try creating a blog post and upload an image. You
should be able to see the uploaded image in public/img of your local
directory.
Saving Uploaded Images to Database
In BlogPost.js, add a image variable of type string to store the file path of the
image as shown:

const BlogPostSchema = new Schema({
title: String,
body: String,
username: String,
datePosted:{
type: Date,
default: new Date()
},
image: String
});

In index.js, specify the full image file path to the BlogPost image attribute in
create() as shown below:
app.post(‘/posts/store’, (req,res)=>{
let image = req.files.image;
image.mv(path.resolve(__dirname,’public/img’,image.name),async
(error)=>{
await BlogPost.create({
…req.body,
image: ‘/img/’ + image.name
})
res.redirect(‘/’)
})
})
When you run your app now, the new blog post will contain the image file
path.
To display the image in the post view, in post.ejs, change the hardcoded
filepath from
to:
Now when you run your app and navigate to a specific blog post page with an
image, it should show the image in the view (fig. 7.2).
Figure 7.2
Summary
In this chapter, we explored how to upload images for each blog post and
storing them in the server.
Refer to https://github.com/greglim81/express_chap3-8 for the source code of
this chapter. If you face any issues, contact me at support@i-ducate.com
CHAPTER 8: INTRODUCTION TO EXPRESS
MIDDLEWARE
Middleware are functions that Express executes in the middle after the
incoming request which then produces an output which could either be the
final output or be used by the next middleware. We can have more than one
middleware and they will execute in the order they are declared. In the
process, middlewares might make changes to the request and response
objects.
We have actually been using middlewares. In index.js, when we have
app.use( … ), we are in fact applying middlewares to Express. We have for
example declared the following middlewares:
app.use(express.static(‘public’))
app.use(bodyParser.json())
app.use(bodyParser.urlencoded({extended:true}))
app.use(fileUpload())
The use function registers a middleware with our Express app. So, when a
browser makes a request to a page for example, Express will execute all the
‘ use ’ statements sequentially before handling the request.
With app.use(fileUpload()), the fileUpload middleware modifies the request
object and adds the request.files property to it. Without the fileupload
middleware, uploading a file and retrieving it would be much more difficult!
Custom Middleware
You can even create your own custom middleware. For example, in index.js,
add the following code to create a custom middleware:

const customMiddleWare = (req,res,next)=>{
console.log(‘Custom middle ware called’)
next()
}
app.use(customMiddleWare)

Now each time you refresh your app, the message ‘Custom middle ware
called’ will be logged in the console.
next() tells Express that the middleware is done and Express should call the
next middleware function. If you remove next() and go to your app in the
browser, the app will hang as you have not told Express to proceed on to the
next middleware function. All middlewares called by app.use calls next().
Registering Validation Middleware
A good use case of using a middleware is in form validation, where we check
for the validity of form field values (field not blank etc.) Without form
validation, our app currently crashes if we submit an empty new post form.
We get an error TypeError: Cannot read property ‘image’ of null because the
image property cannot be null.
With a validation middleware, Express checks to see if data filled in the fields
is valid before sending the request to the server. Create the validation
middleware with the below code:

const validateMiddleWare = (req,res,next)=>{
if(req.files == null || req.body.title == null || req.body.title == null){
return res.redirect(‘/posts/new’)
}
next()
}

The validateMiddleWare middleware simply checks if any of the form fields are
null (which means that they are not entered by the user) and if so, redirect
them back to the create post page.
If we apply the middleware to our application using
app.use(validateMiddleWare), this middleware will be executed for all
request whereas we only want it to be executed for the request to create posts.
Thus, to apply middleware for specific url requests, we do:

app.use(‘/posts/store’,validateMiddleWare)

That is, if Express sees a request from the given url ‘ /posts/store ’ , then
execute the middleware validateMiddleWare. Note: make sure the above
statement is after app.use(fileUpload()) since we depend on the req object
having the files property.
When you run your app and try to submit a create post form with one of the
fields missing, you will be re-directed to the form page. Only when you have
all fields filled in will your submission be successful.
Summary
We were introduced to middlewares in Express and how they add
functionality to our application by adding features to the request and respond
objects. We made use of the validation middleware to do form validation.
Refer to https://github.com/greglim81/express_chap3-8 for the source code of
this chapter. If you face any issues, contact me at support@i-ducate.com
CHAPTER 9: REFACTORING TO MVC
Till now, we have been putting all our code into index.js. For example, all the
request handlers app.get, app.post are in the same file. This is not the best
approach when our app grows or if we are building a more complex app as
index.js becomes too complicated and unmanageable. Thus, we will refactor
our code adhering to a common pattern called the Model-View-Controller or
MVC pattern.
That is, we divide our application into three interconnected parts, Model,
View and Controller:
– Model represents the structure of the data, the format and the constraints
with which it is stored. In essence, it is the database part of the application.
As you might already notice, we already have that in our models folder
currently storing the BlogPost model.
– View is what is presented to the user. Views make use of the Model and
present data in a manner which the user wants. From the view, user can make
changes to the data presented to them. In our app, the View consist of static
or dynamic pages rendered to users. The pages are stored in a views folder
storing various EJS files to render static and dynamic HTML websites.
– Lastly, we have Controller which controls the requests of the user and then
generates appropriate response rendered back to the user. That is, a user
interacts with the View which generates the appropriate request which is
handled by the Controller which then renders the appropriate view with the
Model data as a response.
We already have the Model and View layer. In this chapter, we will refactor
our code to create a Controller layer by creating a controllers folder to store
our request handlers.
So, create a new folder controllers, and in it create a new file newPost.js.
This file will contain the controller handling the request from the user to
create a new blog post.
In newPost.js, fill in the code with:
module.exports = (req, res) =>{
res.render(‘create’)
}
In index.js, we then replace the below request handler
app.get(‘/posts/new’,(req,res)=>{
res.render(‘create’)
})
with:
const newPostController = require(‘./controllers/newPost’)

app.get(‘/posts/new’,newPostController)
That is, we move the existing request handler function to a separate controller
file newPost.js. This helps to make index.js smaller and provide better
organization by separating controller details each into their own file.
Try It Out
As an exercise, try on your own to create individual controller files for the
other request handler functions.
Have you tried them? Let ’ s go through it together now. For simplicity in our
project and to allow us to focus on the essentials, we will remove the About,
Contact and Sample Post pages since they are just standard static HTML
pages.
So, in index.js, remove:
app.get(‘/about’,(req,res)=>{
res.render(‘about’);
})
app.get(‘/contact’,(req,res)=>{
res.render(‘contact’);
})
app.get(‘/post’,(req,res)=>{
res.render(‘post’)
})
We would also have to remove their links from navbar.ejs:
Home
About
Sample Post
Contact
New Post
This leaves us to refactor the home page, store post and get individual post
request handler. In controllers folder, create home.js, storePost.js and
getPost.js as shown below:
home.js
const BlogPost = require(‘../models/BlogPost.js’)
module.exports = async (req, res) =>{
const blogposts = await BlogPost.find({})
res.render(‘index’,{
blogposts
});
}
Note that we have to import the model Blog…

Save Time On Research and Writing
Hire a Pro to Write You a 100% Plagiarism-Free Paper.
Get My Paper
Still stressed from student homework?
Get quality assistance from academic writers!

Order your essay today and save 25% with the discount code LAVENDER