useFormValidation Composable
Simple form validation composable with custom rules and error messages
Code
import { ref, type Ref } from 'vue';
type ValidationRule<T> = (value: T) => string | null;
interface FormErrors<T> {
[K in keyof T]?: string;
}
export function useFormValidation<T extends Record<string, any>>(
formData: Ref<T>,
validationRules: { [K in keyof T]: ValidationRule<T[K]> }
) {
const errors = ref<FormErrors<T>>({}) as Ref<FormErrors<T>>;
const isValid = ref(false);
// Validate single field
const validateField = (field: keyof T) => {
const rule = validationRules[field];
__TOKEN_31__ (!rule) return;
errors.value[field] = rule(formData.value[field]);
};
// Validate entire form
const validateForm = (): boolean => {
const formErrors: FormErrors<T> = {};
Object.keys(validationRules).forEach((field) => {
const key = field as keyof T;
const error = validationRules[key](formData.value[key]);
__TOKEN_37__ (error) formErrors[key] = error;
});
errors.value = formErrors;
isValid.value = Object.keys(formErrors).length === 0;
return isValid.value;
};
// Reset errors
const resetErrors = () => {
errors.value = {};
isValid.value = false;
};
return {
errors,
isValid,
validateField,
validateForm,
resetErrors
};
}
// Usage example
// const formData = ref({
// email: '',
// password: ''
// });
// const validationRules = {
// email: (val) => !val ? 'Email is required' : !/^\S+@\S+\.\S+$/.test(val) ? 'Invalid email' : null,
// password: (val) => !val ? 'Password is required' : val.length < 6 ? 'Password must be at least 6 chars' : null
// };
// const { errors, validateForm } = useFormValidation(formData, validationRules);
// const submit = () => {
// if (validateForm()) { /* submit form */ }
// };