data validation in express

Implement data validation in Express

Data validation is an important part of software development. It makes sure that input data is accurate and meets the requirements before processing or storing it. With Sequelize, it's easy and flexible to validate data.

This guide will teach you how to use data validation in Express API, helping you build secure and reliable applications. From using built-in Sequelize validations to making validation logic.

Prerequisites

  • Node.js

Setup project

Setting up the Node.js project dependencies.

npm install express sequelize sqlite3

Project structure

├─ index.js
├─ models
│  └─ user.js
└─ public
   └─ index.html

Project files

model.js

This file defines the Sequelize user model and specifies validation configurations for each field to enforce the required validation rules.

const Sequelize = require('sequelize')

sequelize = new Sequelize('sqlite::memory:')

module.exports = sequelize.define('User', {
  id: {
    type: Sequelize.INTEGER,
    primaryKey: true,
    allowNull: false,
    validate: {
      notEmpty: {
        msg: 'Required'
      }
    }
  },
  name: {
    type: Sequelize.STRING,
    validate: {
      len: {
        args: [0, 10],
        msg: 'Maximum length is 10'
      }
    }
  },
  email: {
    type: Sequelize.STRING,
    validate: {
      isEmail: {
        msg: 'Invalid email address'
      }
    }
  },
  age: {
    type: Sequelize.INTEGER,
    validate: {
      min: {
        args: 1,
        msg: 'Must between 1 and 100'
      },
      max: {
        args: 100,
        msg: 'Must between 1 and 100'
      }
    }
  },
  birthdate: {
    type: Sequelize.DATEONLY,
    validate: {
      isDate: {
        msg: 'Invalid date format'
      }
    }
  }
})

index.js

This file serves as the main entry point for the Express application, responsible for creating and configuring the Express server. Since the API has a single route for form submission, so the route and its handler function are defined directly in this file.

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

let app = express()
app.use(express.json(), express.static('public'))
app.post('/submit', async (req, res) => {
  let user = await User.build(req.body)
  try {
    await user.validate()
    res.end()
  }
  catch (error) {
    let errors = error.errors.reduce((errors, e) => {
      errors[e.path] = e.message
      return errors
    }, {})
    res.status(400).json(errors)
  }
})
app.listen(8000)

User.build(req.body) creates a user model object from the request input data. user.validate() method then validates the user object. If validation fails, the error messages are returned in the response.

index.html

The HTML user input form is designed to test the validation rules, typically including fields that correspond to the columns of the User model.

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1">
    <link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap/5.3.3/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.jsdelivr.net/npm/vue@3/dist/vue.global.js"></script>
</head>

<body>
    <div id="app" class="container">
        <div class="row mt-3">
            <form @submit.prevent="submit()">
                <div class="mb-3 col-12">
                    <label class="form-label" for="id">Id</label>
                    <input id="id" class="form-control form-control-sm" v-model="user.id" />
                    <span v-if="errors.id" class="text-danger">{{ errors.id }}</span>
                </div>
                <div class="mb-3 col-12">
                    <label class="form-label" for="name">Name</label>
                    <input id="name" class="form-control form-control-sm" v-model="user.name" />
                    <span v-if="errors.name" class="text-danger">{{ errors.name }}</span>
                </div>
                <div class="mb-3 col-12">
                    <label class="form-label" for="email">Email</label>
                    <input id="email" class="form-control form-control-sm" v-model="user.email" />
                    <span v-if="errors.email" class="text-danger">{{ errors.email }}</span>
                </div>
                <div class="mb-3 col-12">
                    <label class="form-label" for="age">Age</label>
                    <input id="age" class="form-control form-control-sm" v-model="user.age" />
                    <span v-if="errors.age" class="text-danger">{{ errors.age }}</span>
                </div>
                <div class="mb-3 col-12">
                    <label class="form-label" for="birthdate">Birth Date</label>
                    <input id="birthdate" class="form-control form-control-sm" v-model="user.birthdate" />
                    <span v-if="errors.birthdate" class="text-danger">{{ errors.birthdate }}</span>
                </div>
                <div class="col-12">
                    <input type="button" class="btn btn-sm btn-danger" @click="fill(0)" value="Fill invaid data" />
                    <input type="button" class="btn btn-sm btn-success ms-1" @click="fill(1)" value="Fill vaid data" />
                    <button class="btn btn-sm btn-primary ms-1">Submit</button>
                </div>
                <div v-if="pass" class="alert alert-success mt-3">
                    Validation success!
                </div>
            </form>
        </div>
    </div>
    <script>
        const { createApp } = Vue
        createApp({
            data() {
                return {
                    user: {},
                    errors: {},
                    pass: false
                }
            },
            methods: {
                fill(valid) {
                    this.user.id = (valid ? '1' : '')
                    this.user.name = (valid ? 'foo' : 'my name is foo')
                    this.user.email = (valid ? 'foo@mail.com' : 'mail')
                    this.user.age = (valid ? '10' : '101')
                    this.user.birthdate = (valid ? '2000-01-01' : '01012000')
                },
                submit() {
                    fetch('/submit', {
                        method: 'POST',
                        headers: {
                            'Content-Type': 'application/json'
                        },
                        body: JSON.stringify(this.user)
                    }).then(res => {
                        if (res.status == 200) {
                            this.pass = true
                            this.errors = {}
                        }
                        else {
                            res.json().then(err => {
                                this.pass = false
                                this.errors = err
                            })
                        }
                    })
                }
            }
        }).mount('#app')
    </script>
</body>

To keep our HTML and JavaScript clean and readable, we utilize Vue's v-model and v-if directives to render the form.

Run project

node index.js

Open the web browser and goto http://localhost:8000
You will find this test page.

test-page

Testing

Click "Fill invalid data" and then click "Submit" to see the error messages displayed in the input form.

validation failed

Click "Fill valid data" and then "Submit" again. You should see the validation success message displayed in the input form.

validation success

Conclusion

This article explored implementing basic form validation, enabling you to create reliable and user-friendly applications. Incorporate these techniques to improve the strength and usability of your Express API.

Source code: https://github.com/stackpuz/Example-Validation-Express

Create a CRUD Web App in Minutes: https://stackpuz.com

Related post