NodeJs Server Side Form Validation using Express-Validator, Body-Parser and EJS

By Raddy in NodeJs ·

Today we are going to do some server-side form validation using the Express-validator, Body-parser and for the view engine, I will be using EJS. This is an introduction video, but it should give you enough knowledge to get you started with form validation.

As you might already know it’s usually good practice to validate user input on Server Side because you can protect against malicious users, who can easily bypass your client-side scripting language and submit dangerous input to the server.

Before we get started with this project you need to have NodeJs installed.

Before we get started, I just wanted to mention that you can also watch the full video if you prefer that format. If you like the content, I would appreciate it if you subscribe to my channel here.

Create a project folder

Let’s get started by creating a folder with your project name. This is where your project is going to live and all packages are installed. Talking about packages, let’s go to the next step and create our server setup.

Setup Server Yo!

To start with our project we need to first generate a file called package.json. It holds various metadata relevant to the project and it’s used to give information to npm that allows identifying the project as well as handle dependencies. Go to the root of the folder, open PowerShell or Termnal and type the following command:

npm init
Initializing new project using NPM in PowerShell

As long as you have NodeJs installed, this should guide you through the setup of your project. Basically answer the required questions in the terminal or just keep pressing enter if you are messing around.

Once you finish with the installation, open your package.json file and just double check to see if everything is looking good.

Now let’s install some dependencies.

Install Dependencies

The dependencies that we need to install are:

I’ve linked each dependency to their official documentation so you can go and explore. I strongly encourage you to do that to see what’s possible.

Alternative templating engine that you can use is PUG. Pug is also nice, but I am getting used to EJS now and I almost like it.

Another important thing that you might want to know is that the bodyParser is no longer bundled as part of Express and so we’ll have to install that too.

Let’s install the dependencies by running the following command in the same project folder of course.

npm install express ejs express-validator nodemon body-parser 

Project Structure

Now let’s create the following project structure, leaving node_modules, readme.md, package-lock and package-json as that should have been automatically generated by now.

šŸ“‚ node_modules
šŸ“‚ views
 šŸŒ register.ejs
 šŸŒ index.ejs
šŸ“œ README.md
šŸŒ app.js
šŸ“œ package-lock.json
šŸ“œ package-json

Setup Nodemon

Before we run our server to see if everything is working as intended, we need to add some more metadata in our package.json file. We need to add Nodemon to start the app as we don’t have to refresh every time we make changes.

Open your package.json file and add the following under scripts

"start": "nodemon app.js"

Your full json file should look something like this (obviously you might have newer versions of the packages):

{
  "name": "express-validator-tut",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "nodemon app.js"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "ejs": "^3.1.3",
    "express": "^4.17.1",
    "express-validator": "^6.6.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.4"
  }
}

Save the file and now you should be able to run your project by simply doing:

npm start

We are getting close, but there are a few more things that we need to do before we are able to see our project. First, we need to add ‘express’ and select a port that NodeJs can listen on. Let’s do that.

In your app.js folder add the following code:

// Imports
const express = require('express')
const app = express()
const port = 5000

// Listen on Port 5000
app.listen(port, () => console.info(`App listening on port ${port}`))

Run your app, and see what happens. To do that you can go in your Terminal and type the following command:

npm start

In PowerShell or Terminal (for Mac) you should see a message:

App listening on port 5000unless the port is already taken, then you can change it to 3000 or something like that.

Now if you go on your Internet Browser and visit the URL localhost:5000 you should see a message saying:

Cannot GET /

That’s good. Let’s carry on and fix that.

BodyParser

Include the body parser just after you require express:

const bodyParser = require('body-parser')

There are different modules that we can use such as JSON body parser, Raw body parser, text body parser and url-encoded form body parser, but today we are going to use the Url-encoded form body parser.

Add the following code after you set your View engine:

const urlencodedParser = bodyParser.urlencoded({ extended: false })

Setting Up Our Templating Language

In this application, we are going to work with EJS. There are a lot of options out there that you can choose from and most of them are faily simular. Here is how we can set our templating language using EJS.

// Set View's
app.set('view engine', 'ejs');
const bodyParser = require('body-parser')
const { check, validationResult } = require('express-validator')

Validation Checks

To preform validation checks is actually fairly simple. We need to require the express validator at the top of our project (under the body parser) and then we should be able to use it on POST. Let’s first require the express validator:

const { check, validationResult } = require('express-validator')

Now let’s create a very simple post route:

app.post('/register', urlencodedParser, [
    check('username', 'This username must me 3+ characters long')
        .exists()
        .isLength({ min: 3 }),
    check('email', 'Email is not valid')
        .isEmail()
        .normalizeEmail()
], (req, res)=> {

    const errors = validationResult(req)
    if(!errors.isEmpty()) {
        // return res.status(422).jsonp(errors.array())
        const alert = errors.array()
        res.render('register', {
            alert
        })
    }
})

Our Final Code for APP.JS

const express = require('express')
const bodyParser = require('body-parser')
const { check, validationResult } = require('express-validator')

const app = express()
const port = 5000

// Set Templating Enginge
app.set('view engine', 'ejs')

const urlencodedParser = bodyParser.urlencoded({ extended: false })

// Navigation
app.get('', (req, res)=> {
    res.render('index')
})

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

app.post('/register', urlencodedParser, [
    check('username', 'This username must me 3+ characters long')
        .exists()
        .isLength({ min: 3 }),
    check('email', 'Email is not valid')
        .isEmail()
        .normalizeEmail()
], (req, res)=> {
    const errors = validationResult(req)
    if(!errors.isEmpty()) {
        // return res.status(422).jsonp(errors.array())
        const alert = errors.array()
        res.render('register', {
            alert
        })
    }
})

app.listen(port, () => console.info(`App listening on port: ${port}`))

Register.ejs Page

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <h1>Register</h1>

        <% if(typeof alert != 'undefined') { %>
            <% alert.forEach(function(error) { %>
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
                    <%= error.msg %>
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                      <span aria-hidden="true">Ɨ</span>
                    </button>
                  </div>
            <% }) %>
        <% } %>

        <form action="/register" method="POST">
            <div class="form-group">
                <label for="username" class="form-label">Username</label>
                <input type="text" class="form-control" name="username" id="username">
            </div>
            <div class="form-group">
                <label for="email" class="form-label">Email address</label>
                <input type="email" class="form-control" name="email" id="email">
            </div>
            <div class="form-group">
                <label for="password" class="form-label">Password</label>
                <input type="password" class="form-control" name="password" id="password">
            </div>
            <div class="form-group">
                <label for="password1" class="form-label">Confirm Password</label>
                <input type="password" class="form-control" name="password1" id="password1">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>

    </div>
</body>
</html>

That’s all!

I hope that you found this article helpful. It was written fairly quickly but I will try to revisit it and make it a little bit more organised. If you would like to see more articles and videos like this please consider subscribing to my YouTube channel here.

YouTube Update

If you would like to make the highlighted Bootstrap close alert buttons work you need to include the Bootstrap JS files below. Place one of the following <script>s near the end of your pages, right before the closing </body> tag, to enable them. jQuery must come first, then Popper.js, and then our JavaScript plugins.

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script> 

<script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>

For example your Register.ejs should look something like this:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Register</title>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
    <div class="container">
        <h1>Register</h1>

        <% if(typeof alert != 'undefined') { %>
            <% alert.forEach(function(error) { %>
                <div class="alert alert-warning alert-dismissible fade show" role="alert">
                    <%= error.msg %>
                    <button type="button" class="close" data-dismiss="alert" aria-label="Close">
                      <span aria-hidden="true">&times;</span>
                    </button>
                  </div>
            <% }) %>
        <% } %>

        <form action="/register" method="POST" novalidate>
            <div class="form-group">
                <label for="username" class="form-label">Username</label>
                <input type="text" class="form-control" name="username" id="username">
            </div>
            <div class="form-group">
                <label for="email" class="form-label">Email address</label>
                <input type="email" class="form-control" name="email" id="email">
            </div>
            <div class="form-group">
                <label for="password" class="form-label">Password</label>
                <input type="password" class="form-control" name="password" id="password">
            </div>
            <div class="form-group">
                <label for="password1" class="form-label">Confirm Password</label>
                <input type="password" class="form-control" name="password1" id="password1">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>

    </div>

    <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js" integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx" crossorigin="anonymous"></script>
</body>
</html>
  1. Dilkash Shaikh Mahajan says:

    I got an error where error is *ReferenceError: alert is not defined*.
    I have view your Server side form validation video, and what to do for removing this error

    1. Raddy says:

      Hi Dilkash,

      You have to define “alert” like the example below:


      const alert = errors.array()
      res.render('register', {
      alert
      })

  2. Ajay Ramdayal Sharma says:

    how to give success message registered successfully

    1. Raddy says:

      There are many ways you can do it. Check if your errors array is empty and then add your “Success” message into the alert const. You could push a new object with your alert message. So it might be a case of just adding an if check.

  3. Victor says:

    How to show errors under each input fields using nodejs with express-validator?

    1. Raddy says:

      You can use the bootstrap form validation. Just make sure you include the Bootstrap JS file in your project.

  4. Anto Jacob says:

    The final error message is not showing above the login form . only blank space is showing

    1. Raddy says:

      “Email is not valid” is not showing? I just downloaded the code from GitHub and it seems okay. Can you share your code?

Leave a Reply

Your email address will not be published. Required fields are marked *