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.
Testing
Click "Fill invalid data" and then click "Submit" to see the error messages displayed in the input form.
Click "Fill valid data" and then "Submit" again. You should see the validation success message displayed in the input form.
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