UNPKG

react-validator-dev

Version:

Real-time error messaging and supports field dependencies React hook for form validation

257 lines (229 loc) 7.82 kB
import { useState, useEffect } from "react"; interface ValidationRule { isRequired?: boolean; maxLength?: number; minLength?: number; excludedCharacters?: string[]; regex?: string | any; alpha?: boolean; email?: boolean; numeric?: boolean; date?: boolean; alphaDash?: boolean; alphaSpace?: boolean; sameAsField?: string; } interface ErrorMessage { isRequired?: string; maxLength?: string; minLength?: string; excludedCharacters?: string; regex?: string; alpha?: string; email?: string; numeric?: string; date?: string; alphaDash?: string; alphaSpace?: string; sameAsField?: string; } interface Validation { rules: { [key: string]: ValidationRule }; messages?: { [key: string]: ErrorMessage }; } interface ValidationErrors { errors: Record<string, string>; status: boolean; } const isRequiredCheck = (data: any, errorMessage: string) => !data ? errorMessage : ""; const maxLengthCheck = (data: any, max: number, errorMessage: string) => data.length > max ? errorMessage : ""; const minLengthCheck = (data: any, min: number, errorMessage: string) => data.length < min ? errorMessage : ""; const excludedCharactersCheck = ( data: any, chars: string[], errorMessage: string ) => (chars.some((char) => data.includes(char)) ? errorMessage : ""); const regexCheck = (data: any, regex: string, errorMessage: string) => new RegExp(regex).test(data) ? "" : errorMessage; const alphaCheck = (data: any, errorMessage: string) => /^[A-Za-z]+$/.test(data) ? "" : errorMessage; const emailCheck = (data: string, errorMessage: string) => { const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/; return emailRegex.test(data) ? "" : errorMessage; }; const alphaWithDashCheck = (data: string, errorMessage: string) => { const regex = /^[A-Za-z]+(-[A-Za-z]+)*$/; return regex.test(data) ? "" : errorMessage; }; const numericCheck = (data: string, errorMessage: string) => /^\d+$/.test(data) ? "" : errorMessage; const isDateCheck = (data: string, errorMessage: string) => { const regex = /^\d{4}-\d{2}-\d{2}$/; // Example format YYYY-MM-DD const date = new Date(data); return regex.test(data) && !isNaN(date.getTime()) ? "" : errorMessage; }; const alphaWithSpaceCheck = (data: string, errorMessage: string) => { const regex = /^[A-Za-z]+( [A-Za-z]+)*$/; return regex.test(data) ? "" : errorMessage; }; const sameAsFieldCheck = ( data: string, errorMessage: string, fieldValue: string ) => (data === fieldValue ? "" : errorMessage); const useValidation = ( data: { fields: Record<string, any>; validation: Validation }, isMultiple = false, submit: boolean = true, debounceDelay = 300, validateAll = false ) => { const [errors, setErrors] = useState<ValidationErrors>({ errors: {}, status: true, }); const { fields, validation } = data; const [fieldsInitailStaus, setFieldsInitailStaus] = useState<any>(); const [submitted, setsubmitted] = useState(true); useEffect(() => { let status = { ...fields }; Object.keys(fields).forEach((field) => (status[field] = false)); setFieldsInitailStaus(status); setsubmitted(submit); }, []); const validateC = () => { const newErrors: Record<string, string> | any = {}; Object.keys(fields).forEach((field) => { const multipleMessages: string[] = []; const value = fields[field]; let error = ""; const rules = validation.rules[field]; const messages = validation?.messages?.[field]; let isRequired = false; if (rules?.isRequired) { error = isRequiredCheck( value, messages?.isRequired || `Please enter the ${field}` ); if(error?.length){ isRequired = true; multipleMessages.push(error); } } if ((!error || isMultiple ) && rules?.maxLength !== undefined && !isRequired) { error = maxLengthCheck( value, rules.maxLength, messages?.maxLength || `The ${field} length should be at most ${rules.maxLength}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.minLength !== undefined && !isRequired) { error = minLengthCheck( value, rules.minLength, messages?.minLength || `The ${field} length should be at least ${rules.minLength}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.excludedCharacters && !isRequired) { error = excludedCharactersCheck( value, rules.excludedCharacters, messages?.excludedCharacters || `Please enter valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.regex && !isRequired) { error = regexCheck( value, rules.regex, messages?.regex || `The ${field} format is invalid` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.alpha && !isRequired) { error = alphaCheck( value, messages?.alpha || `Please enter valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.email && !isRequired) { error = emailCheck( value, messages?.email || `Please enter a valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.numeric && !isRequired) { error = numericCheck( value, messages?.numeric || `Please enter a valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.date && !isRequired) { error = isDateCheck( value, messages?.date || `Please enter a valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.alphaDash && !isRequired) { error = alphaWithDashCheck( value, messages?.alphaDash || `Please enter valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.alphaSpace && !isRequired) { error = alphaWithSpaceCheck( value, messages?.alphaSpace || `Please enter valid ${field}` ); error?.length && multipleMessages.push(error); } if ((!error || isMultiple ) && rules?.sameAsField && !isRequired) { const otherFieldValue = fields[rules.sameAsField]; error = sameAsFieldCheck( value, messages?.sameAsField || `Please ensure ${field} matches ${rules.sameAsField}`, otherFieldValue ); error?.length && multipleMessages.push(error); } if (!error.length) { setFieldsInitailStaus({ ...fieldsInitailStaus, [field]: true }); } if (fieldsInitailStaus?.[field] == true || submitted == true) { newErrors[field] = !isMultiple ? error : multipleMessages; } }); if (JSON.stringify(errors.errors) !== JSON.stringify(newErrors)) { const status = Object.values(newErrors).some( (error: any) => error.length ); setErrors({ errors: newErrors, status }); } }; useEffect(() => { const handler = setTimeout(() => { validateC(); }, debounceDelay); return () => { clearTimeout(handler); }; }, [fields, validation, debounceDelay, submitted]); useEffect(() => { validateAll && setsubmitted(true); }, [validateAll]); return [errors]; }; export default useValidation;