LearnAI ToolsCareerPractice BuildsPlayContact
Lesson 3615 min read

Form Validation

Validate form input reactively, showing errors as the user types or submits.

Manual Validation with Computed Properties

For a small form, a computed property per field, deriving directly from v-model state, is often all you need.

<script setup>
import { ref, computed } from 'vue';
const email = ref('');
const emailError = computed(() => {
if (!email.value) return 'Email is required.';
if (!email.value.includes('@')) return 'Enter a valid email.';
return '';
});
</script>
<template>
<input v-model="email" type="email" />
<p v-if="emailError" class="error">{{ emailError }}</p>
</template>

Validating on Submit

For a multi-field form, check all validations together at submit time, and stop the submission if anything fails.

<script setup>
import { ref, computed } from 'vue';
const email = ref('');
const password = ref('');
const errors = computed(() => ({
email: !email.value.includes('@') ? 'Enter a valid email.' : '',
password: password.value.length < 8 ? 'At least 8 characters.' : '',
}));
const isValid = computed(() => !errors.value.email && !errors.value.password);
function handleSubmit() {
if (!isValid.value) return;
// proceed with submission
}
</script>
<template>
<form @submit.prevent="handleSubmit">
<input v-model="email" type="email" />
<p v-if="errors.email">{{ errors.email }}</p>
<input v-model="password" type="password" />
<p v-if="errors.password">{{ errors.password }}</p>
<button type="submit" :disabled="!isValid">Sign Up</button>
</form>
</template>

Showing Errors Only After Interaction

Showing an error the instant the page loads (before the user has typed anything) feels aggressive. Track whether a field has been "touched," and only display its error afterward.

<script setup>
import { ref } from 'vue';
const email = ref('');
const emailTouched = ref(false);
</script>
<template>
<input v-model="email" @blur="emailTouched = true" />
<p v-if="emailTouched && !email.includes('@')">Enter a valid email.</p>
</template>

Using a Validation Library

For larger forms, VeeValidate (often paired with a schema library like Yup or Zod) handles field-level validation state, touched tracking, and error messages consistently, without hand-rolling it for every form.

When to Reach for One

A login form with two fields is fine hand-rolled. A multi-step signup or checkout form with a dozen interdependent fields is where a dedicated library like VeeValidate genuinely pays for itself.

FAQs

Yes, always — client-side validation is for UX; never trust it as your only line of defense, since it can be bypassed entirely.

Not directly — computed properties must be synchronous. For async checks, use a watcher that sets a ref based on the result of an API call.

Summary

Computed properties handle most form validation needs cleanly for small-to-medium forms, with dedicated libraries available once complexity grows. Next, you'll handle errors that occur anywhere in a component tree.

Next Lesson →

Error Handling