How to Set Up Form Validation and Manage Form Instances in Ant Design
Use Form.useForm() to create a form instance, pass it to the <Form> component via the form prop, and define validation rules via the rules prop on <Form.Item> components.
Ant Design's form system, located in the ant-design/ant-design repository, provides a robust validation layer built on top of @rc-component/form. The architecture separates instance management, validation logic, and UI rendering, allowing developers to programmatically control forms while maintaining declarative validation schemas.
Creating and Managing Form Instances
Form instances in Ant Design are created using the Form.useForm hook, which wraps the underlying rc-component form API and adds Ant Design-specific helpers.
Using Form.useForm() Hook
The useForm hook is defined in components/form/hooks/useForm.ts. It returns a FormInstance array where the first element is the instance itself:
const [form] = Form.useForm();
This instance provides imperative methods including validateFields, resetFields, getFieldsValue, and Ant Design-specific extensions like scrollToField and focusField. The implementation maintains an internal itemRef map for field registration, enabling DOM operations like scrolling.
Controlled vs Uncontrolled Instance Management
You can manage the form instance in two modes:
Controlled usage (recommended for complex interactions):
const [form] = Form.useForm();
return (
<Form form={form} onFinish={handleSubmit}>
{/* fields */}
</Form>
);
Uncontrolled usage (internal instance creation):
If you omit the form prop, the <Form> component internally creates its own instance using useForm(form) as a fallback, as seen in components/form/Form.tsx.
The form instance is also exposed via a ref (FormRef) so parent components can call imperative methods. The ref handling in components/form/Form.tsx (lines 27-33) merges rc-form methods with the additional helpers.
Configuring Validation Rules in Ant Design Forms
Validation rules are defined per-field using the rules prop on <Form.Item> components. These rules are passed directly to the rc-component validator.
Built-in Validation Rules
The rules prop accepts an array of Rule objects (types defined in components/form/interface.ts and re-exported from rc-component/form/lib/interface). Common rule types include:
<Form.Item
name="email"
rules={[
{ required: true, message: 'Email is required' },
{ type: 'email', message: 'Invalid email format' },
{ min: 5, message: 'Minimum 5 characters' },
{ pattern: /^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i, message: 'Invalid pattern' }
]}
>
<Input />
</Form.Item>
Custom Async Validators
For complex validation logic, use the validator rule with an async function:
<Form.Item
name="username"
rules={[
{
validator: async (_, value) => {
if (!value) {
return Promise.reject(new Error('Username required'));
}
if (value.length < 6) {
return Promise.reject(new Error('Must be at least 6 characters'));
}
// Async check example
const exists = await checkUsernameExists(value);
if (exists) {
return Promise.reject(new Error('Username already taken'));
}
return Promise.resolve();
},
},
]}
>
<Input />
</Form.Item>
Triggering and Handling Validation
Validation can occur automatically on submit or blur events, or programmatically via the form instance.
Programmatic Validation with validateFields
The validateFields method, available on the form instance, triggers validation for all or specific fields:
// Validate all fields
try {
const values = await form.validateFields();
console.log('Success:', values);
} catch (errorInfo) {
console.log('Validation failed:', errorInfo.errorFields);
}
// Validate specific fields only
await form.validateFields(['username', 'email']);
This method is implemented in the underlying rc-component form and exposed through the wrapper in components/form/hooks/useForm.ts.
Auto-Scrolling to Validation Errors
Ant Design provides built-in scrolling behavior when validation fails. Set scrollToFirstError on the <Form> component:
<Form
form={form}
scrollToFirstError
onFinish={handleSubmit}
>
{/* fields */}
</Form>
The scrollToField method implementation in components/form/hooks/useForm.ts (lines 60-76) resolves the DOM node via getFieldDOMNode and uses scroll-into-view-if-needed to handle the scrolling behavior. You can also call this method manually:
form.scrollToField('fieldName', {
block: 'center',
focus: true
});
Customizing Validation Messages
Validation messages can be customized globally or per-form using the ValidateMessagesContext defined in components/form/validateMessagesContext.tsx. Wrap your form with a custom provider to override default messages:
import { ConfigProvider } from 'antd';
const customMessages = {
required: 'This field is mandatory',
string: {
min: 'Must be at least ${min} characters',
},
};
<ConfigProvider form={{ validateMessages: customMessages }}>
<Form>
{/* fields */}
</Form>
</ConfigProvider>
Summary
- Form Instance Creation: Use
Form.useForm()fromcomponents/form/hooks/useForm.tsto create a controlled form instance with methods likevalidateFields,resetFields, andscrollToField. - Validation Rules: Define rules via the
rulesprop on<Form.Item>, supporting built-in validators, patterns, and custom async functions passed to the rc-component validator. - Programmatic Control: Call
form.validateFields()to trigger validation manually, optionally targeting specific fields, and handle errors via try/catch blocks. - Error Scrolling: Enable
scrollToFirstErroron the<Form>component or manually invokeform.scrollToField()to navigate to invalid fields, implemented usingscroll-into-view-if-neededincomponents/form/hooks/useForm.ts. - Instance Management: Pass the instance via the
formprop for controlled usage, or let<Form>create an internal instance for uncontrolled scenarios, with ref exposure for parent component access.
Frequently Asked Questions
How do I validate specific fields only?
Use the validateFields method with an array of field names: await form.validateFields(['username', 'email']). This triggers validation only for the specified fields while ignoring others, useful for multi-step forms or partial saves.
What is the difference between form.validateFields() and onFinish?
onFinish is a callback prop on <Form> that automatically triggers when validation passes during a submit event, receiving the form values as an argument. form.validateFields() is an imperative method you call manually that returns a Promise resolving with values or rejecting with error information, giving you programmatic control over when validation occurs.
How do I reset validation errors programmatically?
Call form.resetFields() to clear all field values and validation states, or form.setFields([]) to clear errors without resetting values. You can also use form.setFieldsValue() to update specific fields while preserving or clearing their validation status depending on your use case.
Can I use form validation without Form.useForm()?
Yes, you can use the uncontrolled mode by omitting the form prop on <Form>. The component internally creates its own instance using useForm(form) as a fallback. However, you won't have access to the instance methods like validateFields or scrollToField unless you obtain a ref to the form component using FormRef.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →