ant-design/components/form/index.zh-CN.md
二货机器人 c4b9a02036
docs: Add FormItem FAQ with Modal (#21077)
* docs: Add faq

* Update index.en-US.md
2020-01-22 20:20:18 +08:00

15 KiB
Raw Blame History

category subtitle type cols title
Components 表单 数据录入 1 Form

高性能表单控件,自带数据域管理。包含数据录入、校验以及对应样式。

何时使用

  • 用于创建一个实体或收集信息。
  • 需要对输入的数据类型进行校验时。

API

Form

参数 说明 类型 默认值
component 设置 Form 渲染元素,为 false 则不创建 DOM 节点 ComponentType | false form
colon 配置 Form.Item 的 colon 的默认值。表示是否显示 label 后面的冒号 (只有在属性 layout 为 horizontal 时有效) boolean true
fields 通过状态管理(如 redux控制表单字段如非强需求不推荐使用。查看示例 FieldData[] -
form Form.useForm() 创建的 form 控制实例,不提供时会自动创建 FormInstance -
hideRequiredMark 隐藏所有表单项的必选标记 boolean false
initialValues 表单默认值,只有初始化以及重置时生效 object -
labelAlign label 标签的文本对齐方式 left | right right
labelCol label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12}sm: {span: 3, offset: 12} object -
layout 表单布局 horizontal | vertical | inline horizontal
name 表单名称,会作为表单字段 id 前缀使用 string -
size 设置字段组件的尺寸(仅限 antd 组件) small | middle | large -
validateMessages 验证提示模板,说明见下 ValidateMessages -
wrapperCol 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol object -
onFinish 提交表单且数据验证成功后回调事件 Function(values) -
onFinishFailed 提交表单且数据验证失败后回调事件 Function({ values, errorFields, outOfDate }) -
onFieldsChange 字段更新时触发回调事件 Function(changedFields, allFields) -
onValuesChange 字段值更新时触发回调事件 Function(changedValues, allValues) -

validateMessages

Form 为验证提供了默认的错误提示信息,你可以通过配置 validateMessages 属性,修改对应的提示模板。一种常见的使用方式,是配置国际化提示信息:

const validateMessages = {
  required: "'${name}' 是必选字段",
  // ...
};

<Form validateMessages={validateMessages} />;

此外,ConfigProvider 也提供了全局化配置方案,允许统一配置错误提示模板:

const validateMessages = {
  required: "'${name}' 是必选字段",
  // ...
};

<ConfigProvider form={{ validateMessages }}>
  <Form />
</ConfigProvider>;

Form.Item

表单字段组件,用于数据双向绑定、校验、布局等。

参数 说明 类型 默认值
colon 配合 label 属性使用,表示是否显示 label 后面的冒号 boolean true
dependencies 设置依赖字段,说明见下 NamePath[] -
extra 额外的提示信息,和 help 类似,当需要错误信息和提示文案同时出现时,可以使用这个。 string|ReactNode -
getValueFromEvent 设置如何将 event 的值转换成字段值 (..args: any[]) => any -
hasFeedback 配合 validateStatus 属性使用,展示校验状态图标,建议只配合 Input 组件使用 boolean false
help 提示信息,如不设置,则会根据校验规则自动生成 string|ReactNode -
htmlFor 设置子元素 label htmlFor 属性 string -
noStyle true 时不带样式,作为纯字段控件使用 boolean false
label label 标签的文本 string|ReactNode -
labelAlign 标签文本对齐方式 left | right right
labelCol label 标签布局,同 <Col> 组件,设置 span offset 值,如 {span: 3, offset: 12}sm: {span: 3, offset: 12}。你可以通过 Form 的 labelCol 进行统一设置。当和 Form 同时设置时,以 Item 为准 object -
name 字段名,支持数组 NamePath -
normalize 转换字段值给控件 (value, prevValue, prevValues) => any -
required 是否必填,如不设置,则会根据校验规则自动生成 boolean false
rules 校验规则,设置字段的校验逻辑。点击此处查看示例 Rule[] -
shouldUpdate 自定义字段更新逻辑,说明见下 boolean | (prevValue, curValue) => boolean false
trigger 设置收集字段值变更的时机 string onChange
validateStatus 校验状态,如不设置,则会根据校验规则自动生成,可选:'success' 'warning' 'error' 'validating' string -
validateTrigger 设置字段校验的时机 string | string[] onChange
valuePropName 子节点的值的属性,如 Switch 的是 'checked' string 'value'
wrapperCol 需要为输入控件设置布局样式时,使用该属性,用法同 labelCol。你可以通过 Form 的 wrapperCol 进行统一设置。当和 Form 同时设置时,以 Item 为准。 object -

dependencies

当字段间存在依赖关系时使用。如果一个字段设置了 dependencies 属性。那么它所依赖的字段更新时,该字段将自动触发更新与校验。一种常见的场景,就是注册用户表单的“密码”与“确认密码”字段。“确认密码”校验依赖于“密码”字段,设置 dependencies 后,“密码”字段更新会重新触发“校验密码”的校验逻辑。你可以参考具体例子

shouldUpdate

Form 通过增量更新方式,只更新被修改的字段相关组件以达到性能优化目的。大部分场景下,你只需要编写代码或者与 dependencies 属性配合校验即可。而在某些特定场景,例如修改某个字段值后出现新的字段选项、或者纯粹希望表单任意变化都对某一个区域进行渲染。你可以通过 shouldUpdate 修改 Form.Item 的更新逻辑。

shouldUpdatetrueForm 的任意变化都会使该 Form.Item 重新渲染。这对于自定义渲染一些区域十分有帮助:

<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>

你可以参考示例查看具体使用场景。

Form.List

为字段提供数组化管理。

参数 说明 类型 默认值
name 字段名,支持数组 NamePath -
children 渲染函数 (fields: Field[], operation: { add, remove, move }) => React.ReactNode -
<Form.List>
  {fields => (
    <div>
      {fields.map(field => (
        <Form.Item {...field}>
          <Input />
        </Form.Item>
      ))}
    </div>
  )}
</Form.List>

Form.Provider

提供表单间联动功能,其下设置 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>

FormInstance

名称 说明 类型
getFieldValue 获取对应字段名的值 (name: NamePath) => any
getFieldsValue 获取一组字段名对应的值,会按照对应结构返回 (nameList?: NamePath[]) => any
getFieldError 获取对应字段名的错误信息 (name: NamePath) => string[]
getFieldsError 获取一组字段名对应的错误信息,返回为数组形式 (nameList?: NamePath[]) => FieldError[]
isFieldTouched 检查对应字段是否被用户操作过 (name: NamePath) => boolean
isFieldsTouched 检查一组字段是否被用户操作过,allTouchedtrue 时检查是否所有字段都被操作过 (nameList?: NamePath[], allTouched?: boolean) => boolean
isFieldValidating 检查一组字段是否正在校验 (name: NamePath) => boolean
resetFields 重置一组字段到 initialValues (fields?: NamePath[]) => void
scrollToField 滚动到对应字段位置 (name: NamePath, options: [ScrollOptions]) => void
setFields 设置一组字段状态 (fields: FieldData[]) => void
setFieldsValue 设置表单的值 (values) => void
submit 提交表单,与点击 submit 按钮效果相同 () => void
validateFields 触发表单验证 (nameList?: NamePath[]) => Promise

validateFields 返回示例

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

名称 说明 类型
touched 是否被用户操作过 boolean
validating 是否正在校验 boolean
errors 错误信息 string[]
name 字段名称 NamePath[]
value 字段对应值 any

Rule

Rule 支持接收 object 进行配置,也支持 function 来动态获取 from 的数据:

type Rule = RuleConfig | ((form: FormInstance) => RuleConfig);
名称 说明 类型
enum 是否匹配枚举中的值 any[]
len string 类型时为字符串长度number 类型时为确定数字; array 类型时为数组长度 number
max string 类型为字符串最大长度number 类型时为最大值array 类型时为数组最大长度 number
message 错误信息,不设置时会通过模板自动生成 string
min string 类型为字符串最小长度number 类型时为最小值array 类型时为数组最小长度 number
pattern 正则表达式匹配 RegExp
required 是否为必选字段 boolean
transform 将字段值转换成目标值后进行校验 (value) => any
type 类型,常见有 string |number |boolean |url | email。更多请参考此处 string
validator 自定义校验,接收 Promise 作为返回值。示例参考 (rule, value) => Promise
whitespace 如果字段仅包含空格则校验不通过 boolean
validateTrigger 设置触发验证时机,必须是 Form.Item 的 validateTrigger 的子集 string | string[]

从 v3 升级到 v4

如果你是 antd v3 的用户,你可以参考迁移示例

FAQ

自定义 validator 没有效果

这是由于你的 validator 有错误导致 callback 没有执行到。你可以选择通过 async 返回一个 promise 或者使用 try...catch 进行错误捕获:

validator: async (rule, value) => {
  throw new Error('Something wrong!');
}

// or

validator(rule, value, callback) => {
  try {
    throw new Error('Something wrong!');
  } catch (err) {
    callback(err);
  }
}

如何在函数组件中拿到 form 实例?

你需要通过 forwardRefuseImperativeHandle 的组合使用来实现在函数组件中正确拿到 form 实例:

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);

使用表单组件可以写成这样:

const TestForm = () => {
  const formRef = createRef<Ref>();
  return (
    <EnhancedFCForm
      onSubmit={() => console.log(formRef.current!.form.getFieldValue('name'))}
      wrappedComponentRef={formRef}
    />
  );
};

在线示例:

Edit wrappedComponentRef-in-function-component

为何在 Modal 中调用 form 控制台会报错?

Warning: Instance created by useForm is not connect to any Form element. Forget to pass form prop?

这是因为你在调用 form 方法时Modal 还未初始化导致 form 没有关联任何 Form 组件。你可以通过给 Modal 设置 forceRender 将其预渲染。示例点击此处