Nuxt Form Validation: A Comprehensive Tutorial


I'll recommend some popular validation packages for Nuxt.js and show you how to implement them.
The two most recommended validation packages for Nuxt.js are:
Vee-Validate - Most popular, easy to use, and well maintained
Zod - Type-safe validation, great TypeScript support
Yup - Similar to Zod but more established
Let me show you how to implement validation using Vee-Validate, as it's the most commonly used:
First, install Vee-Validate:
npm install vee-validate @vee-validate/rules
Here's an example of a form with validation:
// components/RegisterForm.vue
<template>
<div class="register-form">
<Form @submit="onSubmit" :validation-schema="schema">
<div class="form-group">
<label for="username">Username</label>
<Field
name="username"
type="text"
id="username"
v-slot="{ field, errors }"
>
<input v-bind="field" class="form-input" />
<span class="error" v-if="errors">{{ errors }}</span>
</Field>
</div>
<div class="form-group">
<label for="email">Email</label>
<Field
name="email"
type="email"
id="email"
v-slot="{ field, errors }"
>
<input v-bind="field" class="form-input" />
<span class="error" v-if="errors">{{ errors }}</span>
</Field>
</div>
<div class="form-group">
<label for="password">Password</label>
<Field
name="password"
type="password"
id="password"
v-slot="{ field, errors }"
>
<input v-bind="field" class="form-input" />
<span class="error" v-if="errors">{{ errors }}</span>
</Field>
</div>
<div class="form-group">
<label for="confirmPassword">Confirm Password</label>
<Field
name="confirmPassword"
type="password"
id="confirmPassword"
v-slot="{ field, errors }"
>
<input v-bind="field" class="form-input" />
<span class="error" v-if="errors">{{ errors }}</span>
</Field>
</div>
<button type="submit">Register</button>
</Form>
</div>
</template>
<script setup>
import { Form, Field } from 'vee-validate';
import * as yup from 'yup';
import { useAuthStore } from '~/stores/auth';
const auth = useAuthStore();
// Define validation schema
const schema = yup.object().shape({
username: yup
.string()
.required('Username is required')
.min(3, 'Username must be at least 3 characters')
.max(20, 'Username must be less than 20 characters'),
email: yup
.string()
.required('Email is required')
.email('Must be a valid email'),
password: yup
.string()
.required('Password is required')
.min(8, 'Password must be at least 8 characters')
.matches(/[0-9]/, 'Password must contain at least one number')
.matches(/[A-Z]/, 'Password must contain at least one uppercase letter'),
confirmPassword: yup
.string()
.required('Please confirm your password')
.oneOf([yup.ref('password')], 'Passwords must match')
});
const onSubmit = async (values) => {
try {
await auth.register(values);
// Handle successful registration
} catch (error) {
// Handle registration error
}
};
</script>
<style scoped>
.register-form {
max-width: 400px;
margin: 0 auto;
padding: 20px;
}
.form-group {
margin-bottom: 1rem;
}
.form-input {
width: 100%;
padding: 0.5rem;
border: 1px solid #ddd;
border-radius: 4px;
}
.error {
color: red;
font-size: 0.875rem;
margin-top: 0.25rem;
}
button {
width: 100%;
padding: 0.75rem;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:hover {
background-color: #45a049;
}
</style>
To use Vee-Validate globally in your Nuxt.js application, create a plugin:
// plugins/vee-validate.js import { defineRule } from 'vee-validate'; import { required, email, min, max } from '@vee-validate/rules'; export default defineNuxtPlugin(() => { // Define global validation rules defineRule('required', required); defineRule('email', email); defineRule('min', min); defineRule('max', max); });
Then add it to your
nuxt.config.js
:export default defineNuxtConfig({ plugins: ['~/plugins/vee-validate.js'] });
Alternative Option - Using Zod:
// Example of Zod validation schema import { z } from 'zod'; const userSchema = z.object({ email: z.string().email('Invalid email address'), password: z .string() .min(8, 'Password must be at least 8 characters') .regex(/[A-Z]/, 'Password must contain at least one uppercase letter') .regex(/[0-9]/, 'Password must contain at least one number'), username: z .string() .min(3, 'Username must be at least 3 characters') .max(20, 'Username must be less than 20 characters') });
Key features of Vee-Validate:
Form-level and field-level validation
Custom validation rules
Async validation support
Built-in rules for common validations
Good integration with Vue 3 and Nuxt
Cross-field validation (like password confirmation)
Subscribe to my newsletter
Read articles from kietHT directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

kietHT
kietHT
I am a developer who is highly interested in TypeScript. My tech stack has been full-stack TS such as Angular, React with TypeScript and NodeJS.