mirror of
https://github.com/ant-design/ant-design.git
synced 2024-12-13 07:39:10 +08:00
5ebac5f9d6
* feat: Support form & ConfigProvider set component size * update snapshot * fix lint * rm only * update doc * Table & Card support sizing * Update snapshot * fix lint * update snapshot * flush rest snapshot
340 lines
14 KiB
Markdown
340 lines
14 KiB
Markdown
---
|
||
category: Components
|
||
type: Data Entry
|
||
cols: 1
|
||
title: Form
|
||
---
|
||
|
||
High performance Form component with data scope management. Including data collection, verification, and styles.
|
||
|
||
## When to use
|
||
|
||
- When you need to create a instance or collect information.
|
||
- When you need to validate fields in certain rules.
|
||
|
||
## API
|
||
|
||
### Form
|
||
|
||
| Property | Description | Type | Default |
|
||
| --- | --- | --- | --- |
|
||
| component | Set the Form rendering element. Do not create a DOM node for `false` | ComponentType \| false | form |
|
||
| colon | Configure the default value of `colon` for Form.Item. Indicates whether the colon after the label is displayed (only effective when prop layout is horizontal) | boolean | true |
|
||
| fields | Control of form fields through state management (such as redux). Not recommended for non-strong demand. View [example](#components-form-demo-global-state) | [FieldData](#FieldData)\[] | - |
|
||
| form | Form control instance created by `Form.useForm()`. Automatically created when not provided | [FormInstance](#FormInstance) | - |
|
||
| hideRequiredMark | Hide required mark for all form items | boolean | false |
|
||
| initialValues | Set value by Form initialization or reset | object | - |
|
||
| labelAlign | text align of label of all items | 'left' \| 'right' | 'right' |
|
||
| labelCol | label layout, like `<Col>` component. Set `span` `offset` value like `{span: 3, offset: 12}` or `sm: {span: 3, offset: 12}` | [object](https://ant.design/components/grid/#Col) | - |
|
||
| layout | Form layout | 'horizontal'\|'vertical'\|'inline' | 'horizontal' |
|
||
| name | Form name. Will be the prefix of Field `id` | string | - |
|
||
| size | Set field component size (antd components only) | `small | middle | large` | - |
|
||
| validateMessages | 验证提示模板,说明[见下](#validateMessages) | [ValidateMessages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts) | - |
|
||
| wrapperCol | The layout for input controls, same as `labelCol` | [object](https://ant.design/components/grid/#Col) | - |
|
||
| onFinish | Trigger after submitting the form and verifying data successfully | Function(values) | - |
|
||
| onFinishFailed | Trigger after submitting the form and verifying data failed | Function({ values, errorFields, outOfDate }) | - |
|
||
| onFieldsChange | Trigger when field updated | Function(changedFields, allFields) | - |
|
||
| onValuesChange | Trigger when value updated | Function(changedValues, allValues) | - |
|
||
|
||
### validateMessages
|
||
|
||
Form provides [default verification error messages](https://github.com/react-component/field-form/blob/master/src/utils/messages.ts). You can modify template by configuring `validateMessages` property. A common usage is to configure localization:
|
||
|
||
```jsx
|
||
const validateMessages = {
|
||
required: "'${name}' is required!",
|
||
// ...
|
||
};
|
||
|
||
<Form validateMessages={validateMessages} />;
|
||
```
|
||
|
||
Besides,[ConfigProvider](/components/config-provider/) also provides a global configuration scheme that allows for uniform configuration error notification templates:
|
||
|
||
```jsx
|
||
const validateMessages = {
|
||
required: "'${name}' is Required!",
|
||
// ...
|
||
};
|
||
|
||
<ConfigProvider form={{ validateMessages }}>
|
||
<Form />
|
||
</ConfigProvider>;
|
||
```
|
||
|
||
## Form.Item
|
||
|
||
Form field component for data bidirectional binding, validation, layout, and so on.
|
||
|
||
| Property | Description | Type | Default |
|
||
| --- | --- | --- | --- |
|
||
| colon | Used with `label`, whether to display `:` after label text. | boolean | true |
|
||
| dependencies | Set the dependency field. See [below](#dependencies) | [NamePath](#NamePath)[] | - |
|
||
| extra | The extra prompt message. It is similar to help. Usage example: to display error message and prompt message at the same time | string\|ReactNode | - |
|
||
| getValueFromEvent | Specify how to get value from event or other onChange arguments | (..args: any[]) => any | - |
|
||
| hasFeedback | Used with `validateStatus`, this option specifies the validation status icon. Recommended to be used only with `Input` | boolean | false |
|
||
| help | The prompt message. If not provided, the prompt message will be generated by the validation rule. | string\|ReactNode | - |
|
||
| htmlFor | Set sub label `htmlFor` | string | - |
|
||
| noStyle | No style for `true`, used as a pure field control | boolean | false |
|
||
| label | Label text | string\|ReactNode | - |
|
||
| labelAlign | text align of label | 'left' \| 'right' | 'right' |
|
||
| labelCol | The layout of label. You can set `span` `offset` to something like `{span: 3, offset: 12}` or `sm: {span: 3, offset: 12}` same as with `<Col>`. You can set `labelCol` on Form. If both exists, use Item first | [object](/components/grid/#Col) | - |
|
||
| name | Field name, support array | [NamePath](#NamePath) | - |
|
||
| normalize | Normalize value to form component | (value, prevValue, prevValues) => any | - |
|
||
| required | Whether provided or not, it will be generated by the validation rule | boolean | false |
|
||
| rules | Rules for field validation. Click [here](#components-form-demo-basic) to see an example | [Rule](#Rule)[] | - |
|
||
| shouldUpdate | Custom field update logic. See [bellow](#shouldUpdate) | boolean \| (prevValue, curValue) => boolean | false |
|
||
| trigger | When to collect the value of children node | string | onChange |
|
||
| validateStatus | The validation status. If not provided, it will be generated by validation rule. options: 'success' 'warning' 'error' 'validating' | string | - |
|
||
| validateTrigger | When to validate the value of children node | string \| string[] | onChange |
|
||
| valuePropName | Props of children node, for example, the prop of Switch is 'checked' | string | 'value' |
|
||
| wrapperCol | The layout for input controls, same as `labelCol`. You can set `wrapperCol` on Form. If both exists, use Item first | [object](/components/grid/#Col) | - |
|
||
|
||
### dependencies
|
||
|
||
Used when there are dependencies between fields. If a field has the `dependencies` prop, this field will automatically trigger updates and validations when upstream updated. A common scenario is user register form with "password" and "confirm password" fields. The "Confirm Password" validation depends on the "Password" field. After setting `dependencies`, the "Password" field update will re-trigger the validation of "Check Password". You can refer [examples](#components-form-demo-register).
|
||
|
||
### shouldUpdate
|
||
|
||
Form updates only the modified field-related components for performance optimization purposes by incremental update. In most case, you only need to write code or do validation with the [`dependencies`](#dependencies) property. And in some specific case, such as a new field option appears with a filed value changed, or just want to keep some area updating by form update. You can modify the update logic of Form.Item via the `shouldUpdate`.
|
||
|
||
When `shouldUpdate` is `true`, any Form update will cause the Form.Item to be re-rendered. This is very helpful for custom rendering some areas:
|
||
|
||
```jsx
|
||
<Form.Item shouldUpdate>
|
||
{() => {
|
||
return <pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre>;
|
||
}}
|
||
</Form.Item>
|
||
```
|
||
|
||
You can ref [example](#components-form-demo-horizontal-login) to see detail.
|
||
|
||
When `shouldUpdate` is a function, it will be called by form values update. Providing original values and current value to compare. This is very helpful for rendering additional fields based on values:
|
||
|
||
```jsx
|
||
<Form.Item shouldUpdate={(prevValues, curValues) => prevValues.additional !== curValues.additional}>
|
||
{() => {
|
||
return (
|
||
<Form.Item name="other">
|
||
<Input />
|
||
</Form.Item>
|
||
);
|
||
}}
|
||
</Form.Item>
|
||
```
|
||
|
||
You can ref [example](#components-form-demo-control-hooks) to see detail.
|
||
|
||
## Form.List
|
||
|
||
Provides array management for fields.
|
||
|
||
| Property | Description | Type | Default |
|
||
| --- | --- | --- | --- |
|
||
| name | Field name, support array | [NamePath](#NamePath) | - |
|
||
| children | Render function | (fields: Field[], operation: { add, remove, move }) => React.ReactNode | - |
|
||
|
||
```tsx
|
||
<Form.List>
|
||
{fields => (
|
||
<div>
|
||
{fields.map(field => (
|
||
<Form.Item {...field}>
|
||
<Input />
|
||
</Form.Item>
|
||
))}
|
||
</div>
|
||
)}
|
||
</Form.List>
|
||
```
|
||
|
||
## Form.Provider
|
||
|
||
Provide linkage between forms. If a sub form with `name` prop update, it will auto trigger Provider related events. See [example](#components-form-demo-form-context).
|
||
|
||
| Property | Description | Type | Default |
|
||
| --- | --- | --- | --- |
|
||
| onFormChange | Triggered when a sub form field updates | Function(formName: string, info: { changedFields, forms }) | - |
|
||
| onFormFinish | Triggered when a sub form submits | Function(formName: string, info: { values, forms }) | - |
|
||
|
||
```jsx
|
||
<Form.Provider
|
||
onFormFinish={name => {
|
||
if (name === 'form1') {
|
||
// Do something...
|
||
}
|
||
}}
|
||
>
|
||
<Form name="form1">...</Form>
|
||
<Form name="form2">...</Form>
|
||
</Form.Provider>
|
||
```
|
||
|
||
### FormInstance
|
||
|
||
| Name | Description | Type |
|
||
| --- | --- | --- |
|
||
| getFieldValue | Get the value by the field name | (name: [NamePath](#NamePath)) => any |
|
||
| getFieldsValue | Get values by a set of field names. Return according to the corresponding structure | (nameList?: [NamePath](#NamePath)[]) => any |
|
||
| getFieldError | Get the error messages by the field name | (name: [NamePath](#NamePath)) => string[] |
|
||
| getFieldsError | Get the error messages by the fields name. Return as an array | (nameList?: [NamePath](#NamePath)[]) => FieldError[] |
|
||
| isFieldTouched | Check if a field has been operated | (name: [NamePath](#NamePath)) => boolean |
|
||
| isFieldsTouched | Check if fields have been operated. Check if all fields is touched when `allTouched` is `true` | (nameList?: [NamePath](#NamePath)[], allTouched?: boolean) => boolean |
|
||
| isFieldValidating | Check fields if is in validating | (name: [NamePath](#NamePath)) => boolean |
|
||
| resetFields | Reset fields to `initialValues` | (fields?: [NamePath](#NamePath)[]) => void |
|
||
| scrollToField | Scroll to field position | (name: [NamePath](#NamePath)) => void |
|
||
| setFields | Set fields status | (fields: FieldData[]) => void |
|
||
| setFieldsValue | Set fields value | (values) => void |
|
||
| submit | Submit the form. It's same as click `submit` button | () => void |
|
||
| validateFields | Validate fields | (nameList?: [NamePath](#NamePath)[]) => Promise |
|
||
|
||
#### validateFields return sample
|
||
|
||
```jsx
|
||
validateFields()
|
||
.then(values => {
|
||
/*
|
||
values:
|
||
{
|
||
username: 'username',
|
||
password: 'password',
|
||
}
|
||
*/
|
||
})
|
||
.catch(errorInfo => {
|
||
/*
|
||
errorInfo:
|
||
{
|
||
values: {
|
||
username: 'username',
|
||
password: 'password',
|
||
},
|
||
errorFields: [
|
||
{ password: ['username'], errors: ['Please input your Password!'] },
|
||
],
|
||
outOfDate: false,
|
||
}
|
||
*/
|
||
});
|
||
```
|
||
|
||
### Interface
|
||
|
||
#### NamePath
|
||
|
||
`string | number | (string | number)[]`
|
||
|
||
#### FieldData
|
||
|
||
| Name | Description | Type |
|
||
| ---------- | ------------------------ | ----------------------- |
|
||
| touched | Whether is operated | boolean |
|
||
| validating | Whether is in validating | boolean |
|
||
| errors | Error messages | string[] |
|
||
| name | Field name path | [NamePath](#NamePath)[] |
|
||
| value | Field value | any |
|
||
|
||
#### Rule
|
||
|
||
Rule support config object, an also support function to get config object:
|
||
|
||
```tsx
|
||
type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);
|
||
```
|
||
|
||
| Name | Description | Type |
|
||
| --- | --- | --- |
|
||
| enum | Match enum value | any[] |
|
||
| len | Length of string, number, array | number |
|
||
| max | Max length of string, number, array | number |
|
||
| message | Error message. Will auto generate by [template](#validateMessages) if not provided | string |
|
||
| min | Min length of string, number, array | number |
|
||
| pattern | Regex pattern | RegExp |
|
||
| required | Required field | boolean |
|
||
| transform | Transform value to the rule before validation | (value) => any |
|
||
| type | Normally `string` \|`number` \|`boolean` \|`url` \| `email`. More type to ref [here](https://github.com/yiminghe/async-validator#type) | string |
|
||
| validator | Customize validation rule. Accept Promise as return. [example](#components-form-demo-register)参考 | ([rule](#Rule), value) => Promise |
|
||
| whitespace | Failed if only has whitespace | boolean |
|
||
| validateTrigger | Set validate trigger event. Must be the sub set of `validateTrigger` in Form.Item | string \| string[] |
|
||
|
||
## Migrate to v4
|
||
|
||
If you are the user of v3, you can ref [migrate doc](/components/form/v3)。
|
||
|
||
<style>
|
||
.code-box-demo .ant-form:not(.ant-form-inline):not(.ant-form-vertical) {
|
||
max-width: 600px;
|
||
}
|
||
.markdown.api-container table td:last-child {
|
||
white-space: nowrap;
|
||
word-wrap: break-word;
|
||
}
|
||
</style>
|
||
|
||
## FAQ
|
||
|
||
### Customize validator do not working
|
||
|
||
It caused by your `validator` with some error that `callback` can not be called. You can use `async` instead or use `try...catch` to catch the error:
|
||
|
||
```jsx
|
||
validator: async (rule, value) => {
|
||
throw new Error('Something wrong!');
|
||
}
|
||
|
||
// or
|
||
|
||
validator(rule, value, callback) => {
|
||
try {
|
||
throw new Error('Something wrong!');
|
||
} catch (err) {
|
||
callback(err);
|
||
}
|
||
}
|
||
```
|
||
|
||
### Get form instance from function component
|
||
|
||
You can combine `forwardRef` with `useImperativeHandle` to get form instance:
|
||
|
||
```tsx
|
||
import React, { forwardRef, useImperativeHandle } from 'react';
|
||
import Form, { FormComponentProps } from 'antd/lib/form/Form';
|
||
|
||
const FCForm = forwardRef<FormComponentProps, FCFormProps>(({ form, onSubmit }, ref) => {
|
||
useImperativeHandle(ref, () => ({
|
||
form,
|
||
}));
|
||
`...the rest of your form`;
|
||
});
|
||
const EnhancedFCForm = Form.create<FCFormProps>()(FCForm);
|
||
```
|
||
|
||
You can use your form component like this:
|
||
|
||
```tsx
|
||
const TestForm = () => {
|
||
const formRef = createRef<Ref>();
|
||
return (
|
||
<EnhancedFCForm
|
||
onSubmit={() => console.log(formRef.current!.form.getFieldValue('name'))}
|
||
wrappedComponentRef={formRef}
|
||
/>
|
||
);
|
||
};
|
||
```
|
||
|
||
Online demo:
|
||
|
||
[![Edit wrappedComponentRef-in-function-component](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/wrappedcomponentref-in-function-component-fj43c?fontsize=14&hidenavigation=1&theme=dark)
|
||
|
||
<style>
|
||
.site-form-item-icon {
|
||
color: rgba(0, 0, 0, 0.25);
|
||
}
|
||
[data-theme="dark"] .site-form-item-icon {
|
||
color: rgba(255,255,255,.3);
|
||
}
|
||
</style>
|