JAVASCRIPT
General Form Validation with Vue 3 Composition API
Implement robust and flexible form validation in Vue 3 applications using the Composition API, reactive state, and computed properties for managing validation rules.
// components/RegistrationForm.vue
<template>
<form @submit.prevent="submitForm">
<h2>Register</h2>
<div>
<label for="username">Username:</label>
<input type="text" id="username" v-model="form.username" @blur="validateField('username')">
<p v-if="errors.username" class="error">{{ errors.username }}</p>
</div>
<div>
<label for="email">Email:</label>
<input type="email" id="email" v-model="form.email" @blur="validateField('email')">
<p v-if="errors.email" class="error">{{ errors.email }}</p>
</div>
<div>
<label for="password">Password:</label>
<input type="password" id="password" v-model="form.password" @blur="validateField('password')">
<p v-if="errors.password" class="error">{{ errors.password }}</p>
</div>
<button type="submit" :disabled="!isFormValid">Register</button>
<p v-if="submissionMessage" :class="{ 'success': submissionSuccess, 'error': !submissionSuccess }">{{ submissionMessage }}</p>
</form>
</template>
<script setup>
import { reactive, computed, ref } from 'vue';
const form = reactive({
username: '',
email: '',
password: ''
});
const errors = reactive({
username: '',
email: '',
password: ''
});
const submissionMessage = ref('');
const submissionSuccess = ref(false);
const validateField = (fieldName) => {
errors[fieldName] = ''; // Clear previous error
switch (fieldName) {
case 'username':
if (!form.username) {
errors.username = 'Username is required.';
} else if (form.username.length < 3) {
errors.username = 'Username must be at least 3 characters.';
}
break;
case 'email':
if (!form.email) {
errors.email = 'Email is required.';
} else if (!/^[\w-.]+@([\w-]+\.)+[\w-]{2,4}$/.test(form.email)) {
errors.email = 'Invalid email format.';
}
break;
case 'password':
if (!form.password) {
errors.password = 'Password is required.';
} else if (form.password.length < 6) {
errors.password = 'Password must be at least 6 characters.';
}
break;
}
};
const validateAllFields = () => {
validateField('username');
validateField('email');
validateField('password');
return Object.values(errors).every(error => error === '');
};
const isFormValid = computed(() => {
return form.username !== '' && form.email !== '' && form.password !== '' && Object.values(errors).every(error => error === '');
});
const submitForm = () => {
submissionMessage.value = '';
if (validateAllFields()) {
// Simulate API call
console.log('Form submitted:', form);
submissionSuccess.value = true;
submissionMessage.value = 'Registration successful!';
// Reset form after successful submission if needed
// form.username = ''; form.email = ''; form.password = '';
} else {
console.log('Form has errors:', errors);
submissionSuccess.value = false;
submissionMessage.value = 'Please correct the errors.';
}
};
</script>
<style scoped>
form {
max-width: 400px;
margin: 50px auto;
padding: 20px;
border: 1px solid #ccc;
border-radius: 8px;
background-color: #f9f9f9;
}
div {
margin-bottom: 15px;
}
label {
display: block;
margin-bottom: 5px;
font-weight: bold;
}
input[type="text"],
input[type="email"],
input[type="password"] {
width: 100%;
padding: 8px;
border: 1px solid #ddd;
border-radius: 4px;
box-sizing: border-box;
}
.error {
color: red;
font-size: 0.9em;
margin-top: 5px;
}
button {
padding: 10px 15px;
background-color: #4CAF50;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
button:disabled {
background-color: #cccccc;
cursor: not-allowed;
}
.success {
color: green;
}
</style>
How it works: This snippet demonstrates a general form validation pattern in Vue 3 using the Composition API. Form data and validation errors are managed with `reactive` objects. The `validateField` function checks individual fields, and `validateAllFields` ensures all fields meet criteria before submission. A `computed` property, `isFormValid`, dynamically checks if the form can be submitted, enabling/disabling the button. Error messages are conditionally displayed, providing immediate user feedback.