Form Validator Generator
form-validator-generator
Generate comprehensive form validation logic for React forms with TypeScript. Use when creating signup/login forms, input validation, or user data collection. Includes email regex, password strength, required fields, and error handling.
SKILL.md
Full skill instructions
Form Validator Generator
Generate TypeScript validation logic for React forms with comprehensive error handling.
When to Use
Use this skill when:
- Creating signup or signin forms
- Building forms with multiple fields
- Need client-side validation before submission
- Implementing user input validation
- Creating questionnaires or surveys
Instructions
Step 1: Identify Form Fields
Determine which fields need validation:
- Email addresses
- Passwords (with strength requirements)
- Names (trim whitespace)
- Phone numbers
- Dropdowns/selects (required selections)
- Text areas
- Custom fields
Step 2: Generate Validation Function
Create a TypeScript validation function:
const validateForm = (): boolean => {
const errors: Record<string, string> = {};
// Add validation logic for each field
setValidationErrors(errors);
return Object.keys(errors).length === 0;
};
Step 3: Implement Field-Specific Validation
Add rules for each field type:
Email Validation:
if (!formData.email.trim()) {
errors.email = "Email is required";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
errors.email = "Please enter a valid email address";
}
Password Validation:
if (!formData.password) {
errors.password = "Password is required";
} else if (formData.password.length < 8) {
errors.password = "Password must be at least 8 characters";
}
Password Confirmation:
if (formData.password !== formData.confirmPassword) {
errors.confirmPassword = "Passwords do not match";
}
Required Field:
if (!formData.name.trim()) {
errors.name = "Name is required";
}
Required Select:
if (!formData.softwareExperience) {
errors.softwareExperience = "Please select your experience level";
}
Step 4: Add Real-time Validation
Clear errors as user types:
const handleChange = (field: string, value: string) => {
setFormData((prev) => ({ ...prev, [field]: value }));
// Clear validation error for this field
if (validationErrors[field]) {
setValidationErrors((prev) => {
const newErrors = { ...prev };
delete newErrors[field];
return newErrors;
});
}
};
Step 5: Display Validation Errors
Show errors in UI:
<input
type="email"
value={formData.email}
onChange={(e) => handleChange("email", e.target.value)}
className={validationErrors.email ? styles.error : ""}
/>;
{
validationErrors.email && (
<span className={styles.errorMessage}>{validationErrors.email}</span>
);
}
Complete Example: Signup Form Validation
import { useState } from "react";
interface SignupFormData {
name: string;
email: string;
password: string;
confirmPassword: string;
softwareExperience: string;
aiMlFamiliarity: string;
}
export default function SignupForm() {
const [formData, setFormData] = useState<SignupFormData>({
name: "",
email: "",
password: "",
confirmPassword: "",
softwareExperience: "",
aiMlFamiliarity: "",
});
const [validationErrors, setValidationErrors] = useState<
Record<string, string>
>({});
const validateForm = (): boolean => {
const errors: Record<string, string> = {};
// Name validation
if (!formData.name.trim()) {
errors.name = "Name is required";
}
// Email validation
if (!formData.email.trim()) {
errors.email = "Email is required";
} else if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(formData.email)) {
errors.email = "Please enter a valid email address";
}
// Password validation
if (!formData.password) {
errors.password = "Password is required";
} else if (formData.password.length < 8) {
errors.password = "Password must be at least 8 characters";
}
// Password confirmation
if (formData.password !== formData.confirmPassword) {
errors.confirmPassword = "Passwords do not match";
}
// Required select fields
if (!formData.softwareExperience) {
errors.softwareExperience = "Please select your experience level";
}
if (!formData.aiMlFamiliarity) {
errors.aiMlFamiliarity = "Please select your AI/ML familiarity";
}
setValidationErrors(errors);
return Object.keys(errors).length === 0;
};
const handleSubmit = async (e: React.FormEvent) => {
e.preventDefault();
if (!validateForm()) {
return;
}
// Proceed with form submission
};
return <form onSubmit={handleSubmit}>{/* Form fields */}</form>;
}
Validation Rules Library
Email Patterns
// Basic email
/^[^\s@]+@[^\s@]+\.[^\s@]+$/
// Strict email (RFC 5322)
/^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/
Password Strength
// At least 8 characters
password.length >= 8
// Contains uppercase
/[A-Z]/.test(password)
// Contains number
/\d/.test(password)
// Contains special character
/[!@#$%^&*(),.?":{}|<>]/.test(password)
Phone Numbers
// US phone number
/^\(?([0-9]{3})\)?[-. ]?([0-9]{3})[-. ]?([0-9]{4})$/
// International format
/^\+?[1-9]\d{1,14}$/
URLs
// Basic URL
/^https?:\/\/.+/
// Strict URL
/^https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)$/
Error Message Best Practices
- Be Specific: "Email is required" not "Invalid input"
- Be Helpful: "Password must be at least 8 characters" not "Bad password"
- Be Consistent: Use same tone/style across all messages
- Be Positive: "Please enter your email" not "You forgot email"
TypeScript Types
// Validation errors
type ValidationErrors = Record<string, string>;
// Form data
interface FormData {
[key: string]: string | number | boolean;
}
// Validation rules
type ValidationRule = (value: any) => string | null;
// Field config
interface FieldConfig {
required?: boolean;
pattern?: RegExp;
minLength?: number;
maxLength?: number;
custom?: ValidationRule;
}
Accessibility Considerations
- Link error messages to inputs with
aria-describedby - Use
aria-invalidon fields with errors - Ensure error messages are screen-reader friendly
- Don't rely solely on color to indicate errors
<input
type="email"
id="email"
aria-invalid={!!validationErrors.email}
aria-describedby={validationErrors.email ? "email-error" : undefined}
/>;
{
validationErrors.email && (
<span id="email-error" role="alert">
{validationErrors.email}
</span>
);
}
