VUE

useFormValidation Composable

Simple form validation composable with custom rules and error messages

Vue3ComposablesFormValidationForms

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 */ }
// };