Quick Start
Get up and running with El Form in just a few minutes. Create beautiful, type-safe forms with any validation approach.
Make sure you have React 16.8+ in your project. TypeScript is recommended but optional. El Form works great with Next.js, Vite, and Create React App.
Install El Form
Add the form library to your project
Choose Your Approach
Use AutoForm for quick setup or useForm for custom forms
Add Validation
Use schemas, custom functions, or no validation at all
Installation
Choose your preferred package based on your needs:
pnpm add el-form-react-hooksFor auto-generated forms with styling:
pnpm add el-form-react-componentsQuick Start: AutoForm
The fastest way to create a form is with AutoForm and a Zod schema:
import { AutoForm } from "el-form-react-components";
import "el-form-react-components/styles.css"; // ✨ Beautiful styling
import { z } from "zod";
const contactSchema = z.object({
name: z.string().min(1, "Name is required"),
email: z.string().email("Invalid email"),
message: z.string().min(10, "Message too short"),
});
function ContactForm() {
return (
<AutoForm schema={contactSchema} onSubmit={(data) => console.log(data)} />
);
}
This generates a complete form with validation, error handling, type safety, and beautiful styling!
Alternative: useForm Hook
For custom forms with full control, use the useForm hook:
import { useForm } from "el-form-react-hooks";
function CustomForm() {
const { register, handleSubmit, formState } = useForm({
defaultValues: { email: "", message: "" },
});
return (
<form onSubmit={handleSubmit((data) => console.log(data))}>
<input {...register("email")} placeholder="Email" />
<textarea {...register("message")} placeholder="Message" />
<button type="submit">Submit</button>
</form>
);
}
Validation Options
El Form supports multiple validation approaches:
Schema Validation (Zod)
import { z } from "zod";
const schema = z.object({
email: z.string().email("Invalid email"),
age: z.number().min(18, "Must be 18+"),
});
const form = useForm({
validators: { onChange: schema },
defaultValues: { email: "", age: 18 },
});
Custom Validation Functions
const form = useForm({
validators: {
onChange: ({ values }) => {
if (!values.email?.includes("@")) return "Invalid email";
if (!values.password || values.password.length < 6)
return "Password too short";
return undefined;
},
},
defaultValues: { email: "", password: "" },
});
No Validation (State Management Only)
const form = useForm({
defaultValues: { email: "", message: "" },
// No validators needed!
});
What You Get
Schema-Agnostic
Use Zod, Yup, custom functions, or no validation - your choice
Auto Generation
Generate complete forms from schemas with AutoForm component
Type Safety
Full TypeScript support with automatic type inference
Performance
Optimized with debounced async validation and minimal re-renders
Field Customization
Customize AutoForm fields as needed:
<AutoForm
schema={contactSchema}
fields={[
{
name: "name",
label: "Full Name",
placeholder: "Enter your name",
colSpan: 6,
},
{
name: "email",
label: "Email Address",
placeholder: "you@example.com",
colSpan: 6,
},
{
name: "message",
type: "textarea",
label: "Your Message",
colSpan: 12,
},
]}
layout="grid"
columns={12}
onSubmit={handleSubmit}
/>
Advanced Validation
Mix different validation approaches:
<AutoForm
schema={baseSchema} // Basic validation
validators={customBusinessRules} // Custom business logic
fieldValidators={{
email: {
onChangeAsync: checkEmailAvailable, // Async field validation
asyncDebounceMs: 500,
},
}}
onSubmit={handleSubmit}
/>
Form State Management
For reactive forms, you can watch field values:
const {
register,
handleSubmit,
formState,
watch,
} = useForm({
validators: { onChange: contactSchema },
defaultValues: {
name: "",
email: "",
message: "",
},
});
const onSubmit = async (data) => {
try {
// Simulate API call
await new Promise(resolve => setTimeout(resolve, 1000));
console.log("Form submitted:", data);
} catch (error) {
console.error("Submission failed:", error);
}
};
return (
<form onSubmit={handleSubmit(onSubmit)} className="space-y-4 max-w-md mx-auto">
<div>
<label htmlFor="name" className="block text-sm font-medium text-gray-700">
Name
</label>
<input
{...register("name")}
id="name"
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
/>
{errors.name && (
<p className="mt-1 text-sm text-red-600">{errors.name.message}</p>
)}
</div>
<div>
<label htmlFor="email" className="block text-sm font-medium text-gray-700">
Email
</label>
<input
{...register("email")}
id="email"
type="email"
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
/>
{errors.email && (
<p className="mt-1 text-sm text-red-600">{errors.email.message}</p>
)}
</div>
<div>
<label htmlFor="message" className="block text-sm font-medium text-gray-700">
Message
</label>
<textarea
{...register("message")}
id="message"
rows={4}
className="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
/>
{errors.message && (
<p className="mt-1 text-sm text-red-600">{errors.message.message}</p>
)}
</div>
<button
type="submit"
disabled={isSubmitting}
className="w-full flex justify-center py-2 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 disabled:opacity-50"
> {isSubmitting ? "Submitting..." : "Submit"}
> </button>
</form>
);
}}`}
</CodeBlock>
<Callout type="info" title="Pro Tip">
The `useForm` hook gives you complete control over form state, validation timing, and submission handling while still leveraging Zod's powerful validation capabilities.
</Callout>
## Next Steps
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 my-8">
<div className="group p-6 rounded-xl border border-slate-200 dark:border-slate-700 bg-gradient-to-br from-white to-slate-50 dark:from-slate-800 dark:to-slate-900 hover:shadow-xl transition-all duration-300">
<div className="flex items-center mb-3">
<div className="mr-3 text-2xl p-2 rounded-lg bg-blue-50 dark:bg-blue-900/30 text-blue-600 dark:text-blue-400">
🚀
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
<a href="./guides/auto-form" className="hover:text-blue-600 dark:hover:text-blue-400 transition-colors">
AutoForm Guide
</a>
</h3>
</div>
<p className="text-slate-600 dark:text-slate-400">Learn all the ways to customize auto-generated forms</p>
</div>
<div className="group p-6 rounded-xl border border-slate-200 dark:border-slate-700 bg-gradient-to-br from-white to-slate-50 dark:from-slate-800 dark:to-slate-900 hover:shadow-xl transition-all duration-300">
<div className="flex items-center mb-3">
<div className="mr-3 text-2xl p-2 rounded-lg bg-purple-50 dark:bg-purple-900/30 text-purple-600 dark:text-purple-400">
🎛️
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
<a href="./guides/use-form" className="hover:text-purple-600 dark:hover:text-purple-400 transition-colors">
useForm Hook
</a>
</h3>
</div>
<p className="text-slate-600 dark:text-slate-400">Master advanced form control and state management</p>
</div>
<div className="group p-6 rounded-xl border border-slate-200 dark:border-slate-700 bg-gradient-to-br from-white to-slate-50 dark:from-slate-800 dark:to-slate-900 hover:shadow-xl transition-all duration-300">
<div className="flex items-center mb-3">
<div className="mr-3 text-2xl p-2 rounded-lg bg-green-50 dark:bg-green-900/30 text-green-600 dark:text-green-400">
💡
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
<a href="./examples" className="hover:text-green-600 dark:hover:text-green-400 transition-colors">
Examples
</a>
</h3>
</div>
<p className="text-slate-600 dark:text-slate-400">See common patterns and real-world use cases</p>
</div>
<div className="group p-6 rounded-xl border border-slate-200 dark:border-slate-700 bg-gradient-to-br from-white to-slate-50 dark:from-slate-800 dark:to-slate-900 hover:shadow-xl transition-all duration-300">
<div className="flex items-center mb-3">
<div className="mr-3 text-2xl p-2 rounded-lg bg-orange-50 dark:bg-orange-900/30 text-orange-600 dark:text-orange-400">
🔗
</div>
<h3 className="text-lg font-semibold text-slate-900 dark:text-slate-100">
<a href="./guides/array-fields" className="hover:text-orange-600 dark:hover:text-orange-400 transition-colors">
Arrays
</a>
</h3>
</div>
<p className="text-slate-600 dark:text-slate-400">Handle complex data structures in your forms</p>
</div>
</div>
<div className="mt-12 p-8 bg-gradient-to-r from-blue-50 via-indigo-50 to-purple-50 dark:from-blue-900/20 dark:via-indigo-900/20 dark:to-purple-900/20 rounded-2xl border border-blue-200 dark:border-blue-800 shadow-xl">
<div className="text-center">
<div className="text-4xl mb-4">🚀</div>
<h3 className="text-2xl font-bold text-blue-900 dark:text-blue-100 mb-4">
Ready to build something amazing?
</h3>
<p className="text-lg text-blue-800 dark:text-blue-200 mb-6 max-w-2xl mx-auto leading-relaxed">
El Form makes it easy to create robust, type-safe forms in React. Start with AutoForm for rapid prototyping, then graduate to useForm when you need more control.
</p>
<div className="flex justify-center gap-4">
<a
href="./examples"
className="inline-flex items-center px-6 py-3 bg-blue-600 hover:bg-blue-700 text-white font-semibold rounded-lg transition-colors duration-200 shadow-lg hover:shadow-xl"
>
See Examples →
</a>
<a
href="./concepts/component-reusability"
className="inline-flex items-center px-6 py-3 bg-green-600 hover:bg-green-700 text-white font-semibold rounded-lg transition-colors duration-200 shadow-lg hover:shadow-xl"
>
Form Reusability →
</a>
<a
href="./faq"
className="inline-flex items-center px-6 py-3 bg-white dark:bg-slate-800 text-blue-600 dark:text-blue-400 font-semibold rounded-lg border border-blue-200 dark:border-blue-700 hover:bg-blue-50 dark:hover:bg-slate-700 transition-colors duration-200 shadow-lg hover:shadow-xl"
>
FAQ
</a>
</div>
</div>
</div>