DEV Community

Cover image for How to validate form inputs in an Expressjs app with joi package
CREDO23 for KADEA ACADEMY

Posted on • Updated on

How to validate form inputs in an Expressjs app with joi package

This tutorial requires knowledge of using the expressjs framework

If you have been building web applications using an Express framework or any other Node.js framework, validation plays a crucial role in any web app which requires you to validate the request body.

Why do we need server-side validation?

  • The client side validation is not enough , it is within reach of the client.
  • A user can turn off client-side JavaScript validation and manipulate the data.

In this tutorial, you’ll learn how to validate form in an Express.js app using an open source and popular module called joi. We will be able to avoid data type errors that can be done by a client .

Introduction to joi

The definition on the official web site says :

joi lets you describe your data using a simple, intuitive, and readable schema.

General use of joi

Usage is a two steps process:

  • First, a schema is constructed using the provided types and constraints:
           const schema = Joi.object({
                a: Joi.string(),
                b: Joi.number(),
                c: Joi.string().email()
           });
Enter fullscreen mode Exit fullscreen mode

Note that joi schema objects are immutable which means
every additional rule added (e.g. .min(5)) will return a
new schema object.

  • Second, the value is validated against the defined schema:
           const result = schema.validate({ 
                a: 'a string' 
                b: 243
                c: 'bakerathierry@gmail.com'
            });
Enter fullscreen mode Exit fullscreen mode

If the input is valid, then req.body will be assigned to
result.
If the input is invalid, an explicit error will be thrown
and assigned to result.

In this tutorial we will be using its asynchronous
validation method validateAsync

Let's take a look at a basic user route without any validation module to create a user: /route/user

   router.post('/', userController.createUser)
Enter fullscreen mode Exit fullscreen mode

Now in user controller ./controllers/user

   const User = require('./models/user')

   exports.createUser = (req, res, next) => {

   try{

      const { userName, email, phone, status } = req.body

      if (userName && phone && email)) { 

         const newUser = new User({...req.body})

         const savedUser = newUser.save()

         if(savedUser){

            res.json({
             msg : 'User created successfully',
             data : savedUser,
             error : null,
             success : true
             }))

         }
     }

      }catch(error){
        next(error)
      }
  };
Enter fullscreen mode Exit fullscreen mode

The above code is just a basic example of validating fields on your own.

You can handle some validations in your user model using Mongoose. For best practices, we want to make sure validation happens before business logic.

joi will take care of all these validations and the sanitization of inputs as well.

Installation

  • With npm
   npm insatll joi --save
Enter fullscreen mode Exit fullscreen mode
  • With Yarn
   yarn add joi
Enter fullscreen mode Exit fullscreen mode

Now , let's create a separate file in validation folder which content our schema validation , we have to include the validation module (joi) in this file.

   const joi = require('joi')

   const userSchema = joi.object({
            userName : Joi.string().required(),
            phone : Joi.number().optionnal(),
            email : Joi.string().email().required()
         });

  module.exports = userSchema

Enter fullscreen mode Exit fullscreen mode

For more details about joi , go to joi

In this schema , we mention that :

  • the userName must be :
    • a string ( .string( ) )
    • required ( .required() )
  • the phone number must be :
    • a number ( .number( ) )
  • the email must be :
    • a string ( .string( ) )
    • a valid email ( .email( ) )
    • required ( .required( ) )

As you can see we use .optional( ) method to mention that the field can be missed ( not required )

** Now we can use our schema whenever we want in the app . **

Let's use that in the user controller /controllers/user :

   const User = require('./models/user')
   const userRegisterValidation = 
         require('./validation/userRegister')

   exports.createUser = async (req, res, next) => {

   try{

      const result =         
          await 
          userRegisterValidation.validateAsync({...req.body})

      if (result) { 

         const newUser = new User({...result})

         const savedUser = newUser.save()

         if(savedUser){

            res.json({
             msg : 'User created successfully',
             data : savedUser,
             error : null,
             success : true
             }))

         }
     }

      }catch(error){
        next(error)
      }
  };
Enter fullscreen mode Exit fullscreen mode

If email is missed , a validation error will be thrown :


    error : {
              message : " The email is required "
            } 

Enter fullscreen mode Exit fullscreen mode

If phone is not a number :


    error : {
              message : " The phone must be a number "
            } 

Enter fullscreen mode Exit fullscreen mode

And so one ...

As you can see this module ( joi ) is helpful when it becomes to validate the client's form in server side , it maintain the code quality as well , but focused on business logic .

I have tried my best and hope I covered enough to explain it so that you can get started.

If you encounter any problems, feel free to comment below.
I would be happy to help :)

Top comments (0)