简介
在使用 Ant.Design 构建复杂表单的时候,常常需要表单项根据用户的输入而动态变化。本文列举了作者在实际开发中积累的最佳实践,主要列举了以下两个场景:
- 表单项之前存在依赖关系
- 动态增减不同类别的表单项
表单项之前存在依赖关系
实现代码如下:
<Form>
<Form.Item name="type">
<Radio.Group>
<Radio value="text">文本模块</Radio>
<Radio value="image">图片模块</Radio>
</Radio.Group>
</Form.Item>
<Form.Item dependencies={['type']} noStyle>
{({ getFieldValue }) => {
const type = getFieldValue('type')
if (type === 'text') {
return (
<>
<Form.Item label="文本内容" name="text">
<Input placeholder="请输入文本内容" />
</Form.Item>
<Form.Item label="文本颜色" name="textColor">
<ColorInput placeholder="请输入文本颜色" />
</Form.Item>
</>
)
}
if (type === 'image') {
return (
<Form.Item label="图片内容" name="image">
<UploadSingle type="image" />
</Form.Item>
)
}
return null
}}
</Form.Item>
</Form>
其中,type
表单项的选择会影响到下面表单项的展示。
我们将受影响的表单项使用 <Form.Item dependencies={['type']} noStyle>
的标签包裹起来,使用 props render
来渲染它们。
dependencies
和 props render
同时使用表示:在dependencies
的表单项数据发生变化时重新渲染 props render
内的内容。详见官方文档: dependencies
动态增减不同类别的表单项
官方文档提供的示例演示了基本的 Form.List
的使用方法,但如果想实现增减不同类别的一组表单,我们需要用到Form.List API中children
渲染函数的 add
方法。
export interface FormListOperation {
add: (defaultValue?: StoreValue, insertIndex?: number) => void;
// ...
}
add
方法的第一个参数可以指定添加的这一组表单项的初始值。然后结合上一节介绍的知识,我们就可以实现动态增减不同类别的表单项了。
实现代码如下:
<Form.Item label="模块列表" required>
<Form.List name="moduleList">
{(fields, { add, remove }) => (
<>
{fields.map(({ key, name, ...restField }, index) => (
<React.Fragment key={key}>
<Dropdown
key={`Dropdown-${key}`}
trigger={['click']}
overlay={
<Menu onClick={(e) => add({ type: e.key }, index)}>
<Menu.Item key="text">文本模块</Menu.Item>
<Menu.Item key="image">图片模块</Menu.Item>
</Menu>
}
>
<Button type="dashed" block icon={<PlusCircleOutlined />}>
添加一个模块
</Button>
</Dropdown>
<div key={`Items-${key}`} className="landing-form-block">
<Form.Item {...restField} label="模块类型" name={[name, 'type']}>
<Select disabled>
<Select.Option value="text">文本模块</Select.Option>
<Select.Option value="image">图片模块</Select.Option>
</Select>
</Form.Item>
<Form.Item dependencies={[[name, 'type']]} noStyle>
{({ getFieldValue }) => {
const type = getFieldValue(['moduleList', name, 'type'])
if (type === 'text') {
return (
<>
<Form.Item label="文本内容" name="text">
<Input placeholder="请输入文本内容" />
</Form.Item>
<Form.Item label="文本颜色" name="textColor">
<ColorInput placeholder="请输入文本颜色" />
</Form.Item>
</>
)
}
if (type === 'image') {
return (
<Form.Item label="图片内容" name="image">
<UploadSingle type="image" />
</Form.Item>
)
}
console.warn('unknown type: ', type)
return null
}}
</Form.Item>
<Button
style={{ width: '100%' }}
type="primary"
danger
size="small"
onClick={() => remove(name)}
icon={<DeleteOutlined />}
>
删除
</Button>
</div>
</React.Fragment>
))}
<Dropdown
trigger={['click']}
overlay={
<Menu onClick={(e) => add({ type: e.key })}>
<Menu.Item key="text">文本模块</Menu.Item>
<Menu.Item key="image">图片模块</Menu.Item>
</Menu>
}
>
<Button type="dashed" block icon={<PlusCircleOutlined />}>
添加一个模块
</Button>
</Dropdown>
</>
)}
</Form.List>