【Antd】Form.List的强大之处,Form.List使用方式细微讲解

设想场景

有时候我们会遇到一些复杂的需求,需要用Table嵌套Form.List,逐层嵌套渲染表格表单列表,填写完毕后提交的复杂需求。

由于表单项分布在数据的各个层级里,因此,如何回填表单值就成了一个比较棘手的问题,处理不好,很容易引发一些逻辑bug(例如表单重置后,数据回填、表单校验异常等)

如何处理数据

其实,antd的form实例对象很强,只需要提供给它指定的field和索引i组成的formName(表单项名称)即可自动回填到表单项中,完全不需要人工干预去处理多层级的数据的,如果有需要转换数据结构,也可以先对form实例的指定表单属性进行数据处理,之后再赋值回该属性名即可。

示例:

...

// 初始化设置数据
useEffect(() => {
	// 由于提交的字段格式和回显的字段格式不一致,这边就是进行数据属性的处理
    const newData = reversalFormData(cloneDeep(data));
    // 设置完毕进行重置表单属性值,也就是上面提到的对属性进行转换,也可以自定义对数据处理
    form.setFieldsValue({
        schemeId: newData.schemeId,
        schemeList: newData.schemeList
    });
}, [data, form]);

return
(<div className={styles.formWrap}>
            <Form
                form={form}
                onValuesChange={onValuesChange}
                layout='vertical'
            >
                <Form.Item
                    hidden
                    name='schemeId'
                ></Form.Item>
                <BasicInfo
                    form={form}
                    data={data}
                />
                <ApplyScope form={form} />
                <WelfareInfo
                    form={form}
                    data={data}
                />
                <div className={styles.footer}>
                    <Button
                        className={styles.confirm}
                        onClick={onSubmit}
                        type='primary'
                        style={{ marginRight: 8 }}
                        htmlType='submit'
                    >
                        确定
                    </Button>
                    <Button
                        className={styles.cancel}
                        onClick={onClose}
                    >
                        取消
                    </Button>
                </div>
            </Form>
</div>)

表格+Form的处理方式:子组件的表格处理

const columns = [
{
    title: '基数(MOP)'
    key: 'macaoCardinalityDictValue',
    dataIndex: 'macaoCardinalityDictValue',
    render: (text, record, index) => (
        <SalaryBaseFormItem // 这个是Form.Item表单项的封装组件
            name={['socialSchemeOptionalList', index, 'macaoCardinalityDictValue']}
            label=''
            countryRegionType='MO'
            rules={[{ required: true, message: '请选择'}]}
            selectProps={{
                style: { width: 200 }
            }}
        />
    )
},
{
    title: '基数上限',
    key: 'cardinalityMaximum',
    dataIndex: 'cardinalityMaximum',
    render: (text, record, index) => (
        <Form.Item
            name={['socialSchemeOptionalList', index, 'cardinalityMaximum']}
            rules={[
                { required: true, message: '' },
                ({ getFieldValue }) => ({
                    validator(_, value) {
                    	// 这边包含了对表单项的自定义校验以及赋值的方式
                        const val = getFieldValue(['socialSchemeOptionalList', index, 'cardinalityMinimum']);
                        if (value < val) {
                            form.setFields([
                                {
                                    name: ['socialSchemeOptionalList', index, 'cardinalityMinimum'],
                                    errors: [intl.formatMessage({ id: 'LMID_00038092' })]
                                }
                            ]);
                            return Promise.reject(new Error(intl.formatMessage({ id: 'LMID_00038093' })));
                        }
                        form.setFields([
                            {
                                name: ['socialSchemeOptionalList', index, 'cardinalityMinimum'],
                                errors: undefined
                            }
                        ]);
                        return Promise.resolve();
                    }
                })
            ]}
        >
            <AmountInputNumber
                min={0}
                placeholder={intl.formatMessage({ id: 'LMID_00003499' })}
            />
        </Form.Item>
    )
},
]

...
<Form.Item name={'tableKey'}>
    <VVTable
        bordered
        columns={columns}
        loading={loading}
        dataSource={dataSource}
        // pagination={{ innerPagination: true }}
        sticky
        scroll={{ x: 'max-content' }}
    />
</Form.Item>

Form.List+Form的处理方式:子组件

return (
        <div className={styles.mainlandWelfare}>
            <Form.List name='socialSchemeChinaList'>
                {(fields, { add, remove }) => (
                    <>
                        {fields.length ? (
                            <>
                                {fields.map((field) => {
                                    // 删除户口类型模块
                                    const onRemove = () => {
                                        modal.confirm({
                                            title: '确定删除?',
                                            content: '删除后数据不可恢复,确定删除吗?',
                                            closable: true,
                                            onOk: () => {
                                                form.validateFields([['socialSchemeChinaList', field.name, 'accountTypeMap']], {
                                                    recursive: true
                                                });
                                                remove(field.name);
                                                message.success('删除成功');
                                            }
                                        });
                                    };
                                    return (
                                    	// 这是一个折叠面板,包含头部和内容区
                                        <WelfareCollapse
                                            items={[
                                                {
                                                    key: '1',
                                                    label: (
                                                        <AccountType
                                                            form={form}
                                                            field={field}
                                                        />
                                                    ),
                                                    children: (
                                                        <WelfareTable
                                                            form={form}
                                                            field={field}
                                                        >
                                                            <Button
                                                                type='default'
                                                                block
                                                                onClick={onRemove}
                                                                disabled={fields.length <= 1}
                                                            >
                                                                删除
                                                            </Button>
                                                        </WelfareTable>
                                                    )
                                                }
                                            ]}
                                        ></WelfareCollapse>
                                    );
                                })}
                                <Button
                                    className={styles.addAccountType}
                                    type='link'
                                    onClick={() => add({ details: [{}] })}
                                >
                                    <Icon
                                        icon='iconsystem_tips_line_3_circle-plus'
                                        size={18}
                                    />
                                    添加户口类型
                                </Button>
                            </>
                        ) : null}
                        {!fields.length ? (
                            <div className={styles.empty}>
                                <Empty
                                    image={Empty.NO_RELEASE}
                                    description={'暂无信息'}
                                />
                                <Button
                                    type='primary'
                                    onClick={() => add({ details: [{}] })}
                                >
                                    添加户口类型
                                </Button>
                            </div>
                        ) : null}
                    </>
                )}
            </Form.List>
            {contextHolder}
        </div>
    );
antdForm组件中可以使用List组件进行嵌套使用,实现动态添加表单项的效果。 具体使用方法如下: 1. 在Form组件中使用List组件作为表单项的容器,设置name属性为需要动态添加的表单项的字段名。 2. 在List组件中使用FormItem组件作为每个表单项的容器,设置name属性为表单项的字段名。 3. 在FormItem组件中使用对应的antd表单控件,如Input、Select等,设置name属性为表单项的字段名。 4. 在List组件中使用Button组件作为添加按钮,设置onClick事件为添加表单项的方法。 5. 在添加表单项的方法中,使用Form组件的setFieldsValue方法更新表单数据,添加新的表单项。 6. 在List组件中使用Button组件作为删除按钮,设置onClick事件为删除表单项的方法。 7. 在删除表单项的方法中,使用Form组件的setFieldsValue方法更新表单数据,删除对应的表单项。 示例代码如下: ``` import { Form, Input, Select, Button, List } from 'antd'; const { Option } = Select; const Demo = () => { const [form] = Form.useForm(); const onFinish = (values) => { console.log(values); }; const addFormItem = () => { const { list } = form.getFieldsValue(); const nextList = [...list, { name: '', age: '', gender: '' }]; form.setFieldsValue({ list: nextList }); }; const removeFormItem = (index) => { const { list } = form.getFieldsValue(); const nextList = [...list]; nextList.splice(index, 1); form.setFieldsValue({ list: nextList }); }; return ( <Form form={form} onFinish={onFinish}> <List name="list"> {(fields, { add, remove }) => ( <> {fields.map((field, index) => ( <Form.Item key={field.key} name={[field.name, 'name']} fieldKey={[field.fieldKey, 'name']} rules={[{ required: true, message: '请输入姓名' }]} > <Input placeholder="姓名" /> </Form.Item> <Form.Item key={field.key} name={[field.name, 'age']} fieldKey={[field.fieldKey, 'age']} rules={[{ required: true, message: '请输入年龄' }]} > <Input placeholder="年龄" /> </Form.Item> <Form.Item key={field.key} name={[field.name, 'gender']} fieldKey={[field.fieldKey, 'gender']} rules={[{ required: true, message: '请选择性别' }]} > <Select placeholder="性别"> <Option value="male">男</Option> <Option value="female">女</Option> </Select> </Form.Item> <Button onClick={() => removeFormItem(index)}>删除</Button> ))} <Button onClick={() => addFormItem()}>添加</Button> </> )} </List> <Button htmlType="submit">提交</Button> </Form> ); }; export default Demo; ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

hzxOnlineOk

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值