components/form/index.zh-CN.md
<code src="./demo/basic.tsx">基本使用</code> <code src="./demo/control-hooks.tsx">表单方法调用</code> <code src="./demo/layout.tsx">表单布局</code> <code src="./demo/layout-multiple.tsx">表单混合布局</code> <code src="./demo/disabled.tsx">表单禁用</code> <code src="./demo/variant.tsx" version="5.13.0">表单变体</code> <code src="./demo/required-mark.tsx">必选样式</code> <code src="./demo/size.tsx">表单尺寸</code> <code src="./demo/layout-can-wrap.tsx">表单标签可换行</code> <code src="./demo/warning-only.tsx">非阻塞校验</code> <code src="./demo/useWatch.tsx">字段监听 Hooks</code> <code src="./demo/validate-trigger.tsx">校验时机</code> <code src="./demo/validate-only.tsx">仅校验</code> <code src="./demo/form-item-path.tsx">字段路径前缀</code> <code src="./demo/dynamic-form-item.tsx">动态增减表单项</code> <code src="./demo/dynamic-form-items.tsx">动态增减嵌套字段</code> <code src="./demo/dynamic-form-items-no-style.tsx" debug>动态增减嵌套纯字段</code> <code src="./demo/dynamic-form-items-complex.tsx">复杂的动态增减表单项</code> <code src="./demo/nest-messages.tsx">嵌套结构与校验信息</code> <code src="./demo/complex-form-control.tsx">复杂一点的控件</code> <code src="./demo/customized-form-controls.tsx">自定义表单控件</code> <code src="./demo/global-state.tsx">表单数据存储于上层组件</code> <code src="./demo/form-context.tsx">多表单联动</code> <code src="./demo/inline-login.tsx">内联登录栏</code> <code src="./demo/login.tsx">登录框</code> <code src="./demo/register.tsx">注册新用户</code> <code src="./demo/advanced-search.tsx">高级搜索</code> <code src="./demo/form-in-modal.tsx">弹出层中的新建表单</code> <code src="./demo/time-related-controls.tsx">时间类控件</code> <code src="./demo/without-form-create.tsx">自行处理表单数据</code> <code src="./demo/validate-static.tsx">自定义校验</code> <code src="./demo/dynamic-rule.tsx">动态校验规则</code> <code src="./demo/form-dependencies.tsx">校验与更新依赖</code> <code src="./demo/validate-scroll-to-field.tsx" iframe="360">滑动到错误字段</code> <code src="./demo/validate-other.tsx">校验其他组件</code> <code src="./demo/style-class.tsx" version="6.0.0">自定义语义结构的样式和类</code> <code src="./demo/getValueProps-normalize.tsx">getValueProps + normalize</code> <code src="./demo/disabled-input-debug.tsx" debug>Disabled Input Debug</code> <code src="./demo/label-debug.tsx" debug>测试 label 省略</code> <code src="./demo/col-24-debug.tsx" debug>测试特殊 col 24 用法</code> <code src="./demo/ref-item.tsx" debug>引用字段</code> <code src="./demo/custom-feedback-icons.tsx" debug>Custom feedback icons</code> <code src="./demo/component-token.tsx" debug>组件 Token</code>
通用属性参考:通用属性
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| classNames | 用于自定义组件内部各语义化结构的 class,支持对象或函数 | Record<SemanticDOM, string> | (info: { props })=> Record<SemanticDOM, string> | - | |
| colon | 配置 Form.Item 的 colon 的默认值。表示是否显示 label 后面的冒号 (只有在属性 layout 为 horizontal 时有效) | boolean | true | |
| disabled | 设置表单组件禁用,仅对 antd 组件有效 | boolean | false | 4.21.0 |
| component | 设置 Form 渲染元素,为 false 则不创建 DOM 节点 | ComponentType | false | form | |
| fields | 通过状态管理(如 redux)控制表单字段,如非强需求不推荐使用。查看示例 | FieldData[] | - | |
| form | 经 Form.useForm() 创建的 form 控制实例,不提供时会自动创建 | FormInstance | - | |
| feedbackIcons | 当 Form.Item 有 hasFeedback 属性时可以自定义图标 | FeedbackIcons | - | 5.9.0 |
| initialValues | 表单默认值,只有初始化以及重置时生效 | object | - | |
| labelAlign | label 标签的文本对齐方式 | left | right | right | |
| labelWrap | label 标签的文本换行方式 | boolean | false | 4.18.0 |
| labelCol | label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12} 或 sm: {span: 3, offset: 12} | object | - | |
| layout | 表单布局 | horizontal | vertical | inline | horizontal | |
| name | 表单名称,会作为表单字段 id 前缀使用 | string | - | |
| preserve | 当字段被删除时保留字段值。你可以通过 getFieldsValue(true) 来获取保留字段值 | boolean | true | 4.4.0 |
| requiredMark | 必选样式,可以切换为必选或者可选展示样式。此为 Form 配置,Form.Item 无法单独配置 | boolean | optional | ((label: ReactNode, info: { required: boolean }) => ReactNode) | true | renderProps: 5.9.0 |
| scrollToFirstError | 提交失败自动滚动到第一个错误字段 | boolean | Options | { focus: boolean } | false | focus: 5.24.0 |
| size | 设置字段组件的尺寸(仅限 antd 组件) | small | medium | large | - | |
| styles | 用于自定义组件内部各语义化结构的行内 style,支持对象或函数 | Record<SemanticDOM, CSSProperties> | (info: { props })=> Record<SemanticDOM, CSSProperties> | - | |
| tooltip | 配置提示属性 | TooltipProps & { icon?: ReactNode } | - | 6.3.0 |
| validateMessages | 验证提示模板,说明见下 | ValidateMessages | - | |
| validateTrigger | 统一设置字段触发验证的时机 | string | string[] | onChange | 4.3.0 |
| variant | 表单内控件变体 | outlined | borderless | filled | underlined | outlined | 5.13.0 | underlined: 5.24.0 |
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol | object | - | |
| onFieldsChange | 字段更新时触发回调事件 | function(changedFields, allFields) | - | |
| onFinish | 提交表单且数据验证成功后回调事件 | function(values) | - | |
| onFinishFailed | 提交表单且数据验证失败后回调事件 | function({ values, errorFields, outOfDate }) | - | |
| onValuesChange | 字段值更新时触发回调事件 | function(changedValues, allValues) | - | |
| clearOnDestroy | 当表单被卸载时清空表单值 | boolean | false | 5.18.0 |
支持原生 form 除
onSubmit外的所有属性。
Form 为验证提供了默认的错误提示信息,你可以通过配置 validateMessages 属性,修改对应的提示模板。一种常见的使用方式,是配置国际化提示信息:
const validateMessages = {
required: "'${name}' 是必选字段",
// ...
};
<Form validateMessages={validateMessages} />;
此外,ConfigProvider 也提供了全局化配置方案,允许统一配置错误提示模板:
const validateMessages = {
required: "'${name}' 是必选字段",
// ...
};
<ConfigProvider form={{ validateMessages }}>
<Form />
</ConfigProvider>;
表单字段组件,用于数据双向绑定、校验、布局等。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| colon | 配合 label 属性使用,表示是否显示 label 后面的冒号 | boolean | true | |
| dependencies | 设置依赖字段,说明见下 | NamePath[] | - | |
| extra | 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 | ReactNode | - | |
| getValueFromEvent | 设置如何将 event 的值转换成字段值 | (..args: any[]) => any | - | |
| getValueProps | 为子元素添加额外的属性 (不建议通过 getValueProps 生成动态函数 prop,请直接将其传递给子组件) | (value: any) => Record<string, any> | - | 4.2.0 |
| hasFeedback | 配合 validateStatus 属性使用,展示校验状态图标,建议只配合 Input 组件使用 此外,它还可以通过 Icons 属性获取反馈图标。 | boolean | { icons: FeedbackIcons } | false | icons: 5.9.0 |
| help | 提示信息,如不设置,则会根据校验规则自动生成 | ReactNode | - | |
| hidden | 是否隐藏字段(依然会收集和校验字段) | boolean | false | 4.4.0 |
| htmlFor | 设置子元素 label htmlFor 属性 | string | - | |
| initialValue | 设置子元素默认值,如果与 Form 的 initialValues 冲突则以 Form 为准 | string | - | 4.2.0 |
| label | label 标签的文本,当不需要 label 又需要与冒号对齐,可以设为 null | ReactNode | - | null: 5.22.0 |
| labelAlign | 标签文本对齐方式 | left | right | right | |
| labelCol | label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12} 或 sm: {span: 3, offset: 12}。你可以通过 Form 的 labelCol 进行统一设置,不会作用于嵌套 Item。当和 Form 同时设置时,以 Item 为准 | object | - | |
| messageVariables | 默认验证字段的信息,查看详情 | Record<string, string> | - | 4.7.0 |
| name | 字段名,支持数组 | NamePath | - | |
| normalize | 组件获取值后进行转换,再放入 Form 中。不支持异步 | (value, prevValue, prevValues) => any | - | |
| noStyle | 为 true 时不带样式,作为纯字段控件使用。当自身没有 validateStatus 而父元���存在有 validateStatus 的 Form.Item 会继承父元素的 validateStatus | boolean | false | |
| preserve | 当字段被删除时保留字段值 | boolean | true | 4.4.0 |
| required | 必填样式设置。如不设置,则会根据校验规则自动生成 | boolean | false | |
| rules | 校验规则,设置字段的校验逻辑。点击此处查看示例 | Rule[] | - | |
| shouldUpdate | 自定义字段更新逻辑,说明见下 | boolean | (prevValue, curValue) => boolean | false | |
| tooltip | 配置提示信息 | ReactNode | (TooltipProps & { icon?: ReactNode }) | - | 4.7.0 |
| trigger | 设置收集字段值变更的时机。点击此处查看示例 | string | onChange | |
| validateFirst | 当某一规则校验不通过时,是否停止剩下的规则的校验。设置 parallel 时会并行校验 | boolean | parallel | false | parallel: 4.5.0 |
| validateDebounce | 设置防抖,延迟毫秒数后进行校验 | number | - | 5.9.0 |
| validateStatus | 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' | string | - | |
| validateTrigger | 设置字段校验的时机 | string | string[] | onChange | |
| valuePropName | 子节点的值的属性。注意:Switch、Checkbox 的 valuePropName 应该是 checked,否则无法获取这个两个组件的值。该属性为 getValueProps 的封装,自定义 getValueProps 后会失效 | string | value | |
| wrapperCol | 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol。你可以通过 Form 的 wrapperCol 进行统一设置,不会作用于嵌套 Item。当和 Form 同时设置时,以 Item 为准 | object | - | |
| layout | 表单项布局 | horizontal | vertical | - | 5.18.0 |
被设置了 name 属性的 Form.Item 包装的控件,表单控件会自动添加 value(或 valuePropName 指定的其他属性) onChange(或 trigger 指定的其他属性),数据同步将被 Form 接管,这会导致以下结果:
onChange 来做数据收集同步(你可以使用 Form 的 onValuesChange),但还是可以继续监听 onChange 事件。value 或 defaultValue 等属性来设置表单域的值,默认值可以用 Form 里的 initialValues 来设置。注意 initialValues 不能被 setState 动态更新,你需要用 setFieldsValue 来更新。setState,可以使用 form.setFieldsValue 来动态改变表单值。当字段间存在依赖关系时使用。如果一个字段设置了 dependencies 属性。那么它所依赖的字段更新时,该字段将自动触发更新与校验。一种常见的场景,就是注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段,设置 dependencies 后,“密码”字段更新会重新触发“校验密码”的校验逻辑。你可以参考具体例子。
dependencies 不应和 shouldUpdate 一起使用,因为这可能带来更新逻辑的混乱。
({ status: ValidateStatus, errors: ReactNode, warnings: ReactNode }) => Record<ValidateStatus, ReactNode>
Form 通过增量更新方式,只更新被修改的字段相关组件以达到性能优化目的。大部分场景下,你只需要编写代码或者与 dependencies 属性配合校验即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都对某一个区域进行渲染。你可以通过 shouldUpdate 修改 Form.Item 的更新逻辑。
当 shouldUpdate 为 true 时,Form 的任意变化都会使该 Form.Item 重新渲染。这对于自定义渲染一些区域十分有帮助,要注意 Form.Item 里包裹的子组件必须由函数返回,否则 shouldUpdate 不会起作用:
相关issue:#34500
<Form.Item shouldUpdate>
{() => {
return <pre>{JSON.stringify(form.getFieldsValue(), null, 2)}</pre>;
}}
</Form.Item>
你可以参考示例查看具体使用场景。
当 shouldUpdate 为方法时,表单的每次数值更新都会调用该方法,提供原先的值与当前的值以供你比较是否需要更新。这对于是否根据值来渲染额外字段十分有帮助:
<Form.Item shouldUpdate={(prevValues, curValues) => prevValues.additional !== curValues.additional}>
{() => {
return (
<Form.Item name="other">
<Input />
</Form.Item>
);
}}
</Form.Item>
你可以参考示例查看具体使用场景。
你可以通过 messageVariables 修改 Form.Item 的默认验证信息。
<Form>
<Form.Item
messageVariables={{ another: 'good' }}
label="user"
rules={[{ required: true, message: '${another} is required' }]}
>
<Input />
</Form.Item>
<Form.Item
messageVariables={{ label: 'good' }}
label={<span>user</span>}
rules={[{ required: true, message: '${label} is required' }]}
>
<Input />
</Form.Item>
</Form>
自 5.20.2 起,当你希望不要转译 ${} 时,你可以通过 \\${} 来略过:
{ required: true, message: '${label} is convert, \\${label} is not convert' }
// good is convert, ${label} is not convert
为字段提供数组化管理。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| children | 渲染函数 | (fields: Field[], operation: { add, remove, move }, meta: { errors }) => React.ReactNode | - | |
| initialValue | 设置子元素默认值,如果与 Form 的 initialValues 冲突则以 Form 为准 | any[] | - | 4.9.0 |
| name | 字段名,支持数组。List 本身也是字段,因而 getFieldsValue() 默认会返回 List 下所有值,你可以通过参数改变这一行为 | NamePath | - | |
| rules | 校验规则,仅支持自定义规则。需要配合 ErrorList 一同使用。 | { validator, message }[] | - | 4.7.0 |
<Form.List>
{(fields) =>
fields.map((field) => (
<Form.Item {...field}>
<Input />
</Form.Item>
))
}
</Form.List>
注意:Form.List 下的字段不应该配置 initialValue,你始终应该通过 Form.List 的 initialValue 或者 Form 的 initialValues 来配置。
Form.List 渲染表单相关操作函数。
| 参数 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| add | 新增表单项 | (defaultValue?: any, insertIndex?: number) => void | insertIndex | 4.6.0 |
| move | 移动表单项 | (from: number, to: number) => void | - | |
| remove | 删除表单项 | (index: number | number[]) => void | number[] | 4.5.0 |
4.7.0 新增。错误展示组件,仅限配合 Form.List 的 rules 一同使用。参考示例。
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| errors | 错误列表 | ReactNode[] | - |
提供表单间联动功能,其下设置 name 的 Form 更新时,会自动触发对应事件。查看示例。
| 参数 | 说明 | 类型 | 默认值 |
|---|---|---|---|
| onFormChange | 子表单字段更新时触发 | function(formName: string, info: { changedFields, forms }) | - |
| onFormFinish | 子表单提交时触发 | function(formName: string, info: { values, forms }) | - |
<Form.Provider
onFormFinish={(name) => {
if (name === 'form1') {
// Do something...
}
}}
>
<Form name="form1">...</Form>
<Form name="form2">...</Form>
</Form.Provider>
| 名称 | 说明 | 类型 | 版本 |
|---|---|---|---|
| getFieldError | 获取对应字段名的错误信息 | (name: NamePath) => string[] | |
| getFieldInstance | 获取对应字段实例 | (name: NamePath) => any | 4.4.0 |
| getFieldsError | 获取一组字段名对应的错误信息,返回为数组形式 | (nameList?: NamePath[]) => FieldError[] | |
| getFieldsValue | 获取一组字段名对应的值,会按照对应结构返回。默认返回现存字段值,当调用 getFieldsValue(true) 时返回所有值 | GetFieldsValue | |
| getFieldValue | 获取对应字段名的值 | (name: NamePath) => any | |
| isFieldsTouched | 检查一组字段是否被用户操作过,allTouched 为 true 时检查是否所有字段都被操作过 | (nameList?: NamePath[], allTouched?: boolean) => boolean | |
| isFieldTouched | 检查对应字段是否被用户操作过 | (name: NamePath) => boolean | |
| isFieldValidating | 检查对应字段是否正在校验 | (name: NamePath) => boolean | |
| resetFields | 重置一组字段到 initialValues | (fields?: NamePath[]) => void | |
| scrollToField | 滚动到对应字段位置 | (name: NamePath, options: ScrollOptions | { focus: boolean }) => void | focus: 5.24.0 |
| setFields | 设置一组字段状态 | (fields: FieldData[]) => void | |
| setFieldValue | 设置表单的值(该值将直接传入 form store 中并且重置错误信息。如果你不希望传入对象被修改,请克隆后传入) | (name: NamePath, value: any) => void | 4.22.0 |
| setFieldsValue | 设置表单的值(该值将直接传入 form store 中并且重置错误信息。如果你不希望传入对象被修改,请克隆后传入)。如果你只想修改 Form.List 中单项值,请通过 setFieldValue 进行指定 | (values) => void | |
| submit | 提交表单,与点击 submit 按钮效果相同 | () => void | |
| validateFields | 触发表单验证,设置 recursive 时会递归校验所有包含的路径 | (nameList?: NamePath[], config?: ValidateConfig) => Promise |
export interface ValidateConfig {
// 5.5.0 新增。仅校验内容而不会将错误信息展示到 UI 上。
validateOnly?: boolean;
// 5.9.0 新增。对提供的 `nameList` 与其子路径进行递归校验。
recursive?: boolean;
// 5.11.0 新增。校验 dirty 的字段(touched + validated)。
// 使用 `dirty` 可以很方便的仅校验用户操作过和被校验过的字段。
dirty?: boolean;
}
返回示例:
validateFields()
.then((values) => {
/*
values:
{
username: 'username',
password: 'password',
}
*/
})
.catch((errorInfo) => {
/*
errorInfo:
{
values: {
username: 'username',
password: 'password',
},
errorFields: [
{ name: ['password'], errors: ['Please input your Password!'] },
],
outOfDate: false,
}
*/
});
type Form.useForm = (): [FormInstance]
创建 Form 实例,用于管理所有数据状态。
type Form.useFormInstance = (): FormInstance
4.20.0 新增,获取当前上下文正在使用的 Form 实例,常见于封装子组件消费无需透传 Form 实例:
const Sub = () => {
const form = Form.useFormInstance();
return <Button onClick={() => form.setFieldsValue({})} />;
};
export default () => {
const [form] = Form.useForm();
return (
<Form form={form}>
<Sub />
</Form>
);
};
type Form.useWatch = (namePath: NamePath | (selector: (values: Store) => any), formInstance?: FormInstance | WatchOptions): Value
5.12.0 新增 selector
用于直接获取 form 中字段对应的值。通过该 Hooks 可以与诸如 useSWR 进行联动从而降低维护成本:
const Demo = () => {
const [form] = Form.useForm();
const userName = Form.useWatch('username', form);
const { data: options } = useSWR(`/api/user/${userName}`, fetcher);
return (
<Form form={form}>
<Form.Item name="username">
<AutoComplete options={options} />
</Form.Item>
</Form>
);
};
如果你的组件被包裹在 Form.Item 内部,你可以省略第二个参数,Form.useWatch 会自动找到上层最近的 FormInstance。
useWatch 默认只监听在 Form 中注册的字段,如果需要监听非注册字段,可以通过配置 preserve 进行监听:
const Demo = () => {
const [form] = Form.useForm();
const age = Form.useWatch('age', { form, preserve: true });
console.log(age);
return (
<div>
<Button onClick={() => form.setFieldValue('age', 2)}>Update</Button>
<Form form={form}>
<Form.Item name="name">
<Input />
</Form.Item>
</Form>
</div>
);
};
type Form.Item.useStatus = (): { status: ValidateStatus | undefined, errors: ReactNode[], warnings: ReactNode[] }
4.22.0 新增,可用于获取当前 Form.Item 的校验状态,如果上层没有 Form.Item,status 将会返回 undefined。5.4.0 新增 errors 和 warnings,可用于获取当前 Form.Item 的错误信息和警告信息:
const CustomInput = ({ value, onChange }) => {
const { status, errors } = Form.Item.useStatus();
return (
<input
value={value}
onChange={onChange}
className={`custom-input-${status}`}
placeholder={(errors.length && errors[0]) || ''}
/>
);
};
export default () => (
<Form>
<Form.Item name="username">
<CustomInput />
</Form.Item>
</Form>
);
Form 仅会对变更的 Field 进行刷新,从而避免完整的组件刷新可能引发的性能问题。因而你无法在 render 阶段通过 form.getFieldsValue 来实时获取字段值,而 useWatch 提供了一种特定字段访问的方式,从而使得在当前组件中可以直接消费字段的值。同时,如果为了更好的渲染性能,你可以通过 Field 的 renderProps 仅更新需要更新的部分。而当当前组件更新或者 effect 都不需要消费字段值时,则可以通过 onValuesChange 将数据抛出,从而避免组件更新。
string | number | (string | number)[]
getFieldsValue 提供了多种重载方法:
当不提供 nameList 时,返回所有注册字段,这也包含 List 下所有的值(即便 List 下没有绑定 Item)。
当 nameList 为 true 时,返回 store 中所有的值,包含未注册字段。例如通过 setFieldsValue 设置了不存在的 Item 的值,也可以通过 true 全部获取。
当 nameList 为数组时,返回规定路径的值。需要注意的是,nameList 为嵌套数组。例如你需要某路径值应该如下:
// 单个路径
form.getFieldsValue([['user', 'age']]);
// 多个路径
form.getFieldsValue([
['user', 'age'],
['preset', 'account'],
]);
用于过滤一些字段值,meta 会返回字段相关信息。例如可以用来获取仅被用户修改过的值等等。
type FilterFunc = (meta: { touched: boolean; validating: boolean }) => boolean;
| 名称 | 说明 | 类型 |
|---|---|---|
| errors | 错误信息 | string[] |
| warnings | 警告信息 | string[] |
| name | 字段名称 | NamePath[] |
| touched | 是否被用户操作过 | boolean |
| validating | 是否正在校验 | boolean |
| value | 字段对应值 | any |
Rule 支持接收 object 进行配置,也支持 function 来动态获取 form 的数据:
type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);
| 名称 | 说明 | 类型 | 版本 |
|---|---|---|---|
| defaultField | 仅在 type 为 array 类型时有效,用于指定数组元素的校验规则 | rule | |
| enum | 是否匹配枚举中的值(需要将 type 设置为 enum) | any[] | |
| fields | 仅在 type 为 array 或 object 类型时有效,用于指定子元素的校验规则 | Record<string, rule> | |
| len | string 类型时为字符串长度;number 类型时为确定数字; array 类型时为数组长度 | number | |
| max | 必须设置 type:string 类型为字符串最大长度;number 类型时为最大值;array 类型时为数组最大长度 | number | |
| message | 错误信息,不设置时会通过模板自动生成 | string | ReactElement | |
| min | 必须设置 type:string 类型为字符串最小长度;number 类型时为最小值;array 类型时为数组最小长度 | number | |
| pattern | 正则表达式匹配 | RegExp | |
| required | 是否为必选字段 | boolean | |
| transform | 将字段值转换成目标值后进行校验 | (value) => any | |
| type | 类型,常见有 string |number |boolean |url | email | tel。更多请参考此处 | string | |
| validateTrigger | 设置触发验证时机,必须是 Form.Item 的 validateTrigger 的子集 | string | string[] | |
| validator | 自定义校验,接收 Promise 作为返回值。示例参考 | (rule, value) => Promise | |
| warningOnly | 仅警告,不阻塞表单提交 | boolean | 4.17.0 |
| whitespace | 如果字段仅包含空格则校验不通过,只在 type: 'string' 时生效 | boolean |
| 名称 | 说明 | 类型 | 默认值 | 版本 |
|---|---|---|---|---|
| form | 指定 Form 实例 | FormInstance | 当前 context 中的 Form | 5.4.0 |
| preserve | 是否监视没有对应的 Form.Item 的字段 | boolean | false | 5.4.0 |
<code src="./demo/_semantic.tsx" simplify="true"></code>
<ComponentTokenTable component="Form"></ComponentTokenTable>
disabled 禁用? {#faq-segmented-cannot-disabled}Segmented 设计上为数据展示类组件,而非表单控件组件。虽然它可以作为类似 Radio 的表单控件使用,但并非为此设计。因而行为上更类似于 Tabs 组件,不会被 Form 的 disabled 所禁用。相关讨论参考 #54749。
Form.Item 默认绑定值属性到 value 上,而 Switch、Checkbox 等组件的值属性为 checked。你可以通过 valuePropName 来修改绑定的值属性。
<Form.Item name="fieldA" valuePropName="checked">
<Switch />
</Form.Item>
当 name 为数组时,会按照顺序填充路径。当存在数字且 form store 中没有该字段时会自动转变成数组。因而如果需要数组为 key 时请使用 string 如:['1', 'name']。
Warning: Instance created by
useFormis not connect to any Form element. Forget to passformprop?
这是因为你在调用 form 方法时,Modal 还未初始化导致 form 没有关联任何 Form 组件。你可以通过给 Modal 设置 forceRender 将其预渲染。示例点击此处。
defaultValue 不生效? {#faq-item-default-value}当你为 Form.Item 设置 name 属性后,子组件会转为受控模式。因而 defaultValue 不会生效。你需要在 Form 上通过 initialValues 设置默认值。
ref 的 Form 为空? {#faq-ref-first-call}ref 仅在节点被加载时才会被赋值,请参考 React 官方文档:https://zh-hans.react.dev/learn/manipulating-the-dom-with-refs#when-react-attaches-the-refs
resetFields 会重新 mount 组件? {#faq-reset-fields-mount}resetFields 会重置整个 Field,因而其子组件也会重新 mount 从而消除自定义组件可能存在的副作用(例如异步数据、状态等等)。
在大部分场景下,我们总是推荐优先使用 Form 的 initialValues。只有存在动态字段时你才应该使用 Item 的 initialValue。默认值遵循以下规则:
initialValues 拥有最高优先级initialValue 次之 *. 多个同 name Item 都设置 initialValue 时,则 Item 的 initialValue 不生效getFieldsValue 在初次渲染的时候拿不到值? {#faq-get-fields-value}getFieldsValue 默认返回收集的字段数据,而在初次渲染时 Form.Item 节点尚未渲染,因而无法收集到数据。你可以通过 getFieldsValue(true) 来获取所有字段数据。
setFieldsValue 设置字段为 undefined 时,有的组件不会重置为空? {#faq-set-fields-undefined}在 React 中,value 从确定值改为 undefined 表示从受控变为非受控,因而不会重置展示值(但是 Form 中的值确实已经改变)。你可以通过 HOC 改变这一逻辑:
const MyInput = ({
// 强制保持受控逻辑
value = '',
...rest
}) => <input value={value} {...rest} />;
<Form.Item name="my">
<MyInput />
</Form.Item>;
rules 后更改值 onFieldsChange 会触发三次? {#faq-rules-trigger-three-times}字段除了本身的值变化外,校验也是其状态之一。因而在触发字段变化会经历以下几个阶段:
在触发过程中,调用 isFieldValidating 会经历 false > true > false 的变化过程。
label 还需要使用 ErrorList 展示错误? {#faq-form-list-no-label}Form.List 本身是 renderProps,内部样式非常自由。因而默认配置 label 和 error 节点很难与之配合。如果你需要 antd 样式的 label,可以通过外部包裹 Form.Item 来实现。
dependencies 对 Form.List 下的字段没有效果? {#faq-dependencies-form-list}Form.List 下的字段需要包裹 Form.List 本身的 name,比如:
<Form.List name="users">
{(fields) =>
fields.map((field) => (
<React.Fragment key={field.key}>
<Form.Item name={[field.name, 'name']} {...someRest1} />
<Form.Item name={[field.name, 'age']} {...someRest1} />
</React.Fragment>
))
}
</Form.List>
依赖则是:['users', 0, 'name']
normalize 不能是异步方法? {#faq-normalize-async}React 中异步更新会导致受控组件交互行为异常。当用户交互触发 onChange 后,通过异步改变值会导致组件 value 不会立刻更新,使得组件呈现假死状态。如果你需要异步触发变更,请通过自定义组件实现内部异步状态。
scrollToFirstError 和 scrollToField 失效? {#faq-scroll-not-working}从 5.17.0 版本开始,滑动操作将优先使用表单控件元素所转发的 ref 元素。因此,在考虑自定义组件支持校验滚动时,请优先考虑将其转发给表单控件元素。
滚动依赖于表单控件元素上绑定的 id 字段,如果自定义控件没有将 id 赋到正确的元素上,这个功能将失效。你可以参考这个 codesandbox。
页面内如果有多个表单,且存在表单项 name 重复,表单滚动定位可能会查找到另一个表单的同名表单项上。需要给表单 Form 组件设置不同的 name 以区分。
ref 绑定元素? {#faq-ref-binding}当自定义组件不支持 ref 时,Form 无法获取子元素真实 DOM 节点,而通过包裹 Class Component 调用 findDOMNode 会在 React Strict Mode 下触发警告。因而我们使用 id 来进行元素定位。
setFieldsValue 不会触发 onFieldsChange 和 onValuesChange? {#faq-set-fields-no-trigger}是的,change 事件仅当用户交互才会触发。该设计是为了防止在 change 事件中调用 setFieldsValue 导致的循环问题。如果仅仅需要组件内消费,可以通过 useWatch 或者 Field.renderProps 来实现。
Form.Item 在渲染时会注入 value 与 onChange 事件给子元素,当你的字段组件被包裹时属性将无法传递。所以以下代码是不会生效的:
<Form.Item name="input">
<div>
<h3>I am a wrapped Input</h3>
<Input />
</div>
</Form.Item>
你可以通过 HOC 自定义组件形式来解决这个问题:
const MyInput = (props) => (
<div>
<h3>I am a wrapped Input</h3>
<Input {...props} />
</div>
);
<Form.Item name="input">
<MyInput />
</Form.Item>;
表单 label 使用 HTML label 元素来包裹表单控件,从而实现点击 label 时聚焦到对应控件。这是 label 元素的原生行为,用于提升可访问性和用户体验,这种标准交互模式能让用户更容易操作表单控件。如果你不希望这种行为,可通过 htmlFor={null} 属性解除关联,通常不建议这样做。
- <Form.Item name="switch" label="Switch">
+ <Form.Item name="switch" label="Switch" htmlFor={null}>
<Switch />
</Form.Item>