How to validate form inputs in an Expressjs app with joi package
Tags: express, validation, javascript
Published: 2022-10-31 19:06:37


>_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](https://joi.dev/api/?v=17.6.1#introduction)

The definition on the official web site says : 

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

<br/>

## General use of [joi](https://joi.dev/api/?v=17.6.1#general-usage)

Usage is a two steps process:<br/>

   - First, a schema is constructed using the provided types 
     and constraints:


   ```javascript
           const schema = Joi.object({
                a: Joi.string(),
                b: Joi.number(),
                c: Joi.string().email()
           });
   ```

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


   - Second, the value is validated against the defined 
     schema:

   ```javascript 
           const result = schema.validate({ 
                a: 'a string' 
                b: 243
                c: 'bakerathierry@gmail.com'
            });
   ```
 
   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.<br/><br/>

 > In this tutorial we will be using its asynchronous 
   validation method _validateAsync_ 

<br/><br/>

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

```javascript
   router.post('/', userController.createUser)
```
  <br/>

Now in user controller `./controllers/user`

```javascript
   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)
      }
  };
```
The above code is just a basic example of validating fields on your own.<br/>

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

joi will take care of all these validations and the sanitization of inputs as well.<br/>

##Installation
- With npm
```javascript
   npm insatll joi --save
```
- With Yarn
```javascript
   yarn add joi
```
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.

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

  module.exports = userSchema
   
```
For more details about joi , go to [joi](https://joi.dev/api/?v=17.6.1#general-usage)

> _In this schema , we mention that :_<br/>
> * _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( )   )_

<br/>

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


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

<br/><br/>

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


```javascript
   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)
      }
  };
```
If email is missed , a validation error will be thrown : 

```javascript

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

```
If phone is not a number : 
```javascript

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

```
<br/> 

And so one ...

<br/>

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 .

<br/>

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

<br/>

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