Form.List实现多层嵌套动态添加表格antd+hooks+ts

功能如下

1.默认无数据,点击绿色新增按钮,会动态添加条件组
2.新增的动态条件组中都有新增子组件的按钮,可以在组中,在动态添加子组件
数据结构如下:

 "inGroups": [
        {
            "conGroup": [
                {
                    "xxx": null,
                    "yyy": 1,
                    "zzz": 1,
                },
                {
                    "xxx": 1,
                    "yyy": 2,
                    "zzz": null,
                }
            ]
        },
        {
            "conGroup": [
                {
                    "xxx": null,
                    "yyy": 1,
                    "zzz": 1,
                },
                {
                    "xxx": 1,
                    "yyy": 2,
                    "zzz": null,
                }
            ]
        }
    ]

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码
import React, { useEffect, useState } from 'react';
import { Modal, Form, Select, Space, Input, DatePicker } from 'antd';
import moment from 'moment';

import styles from './index.less';

const INTENTION_VAR = {};
const { RangePicker } = DatePicker;

interface IModalProps {
  store: any;
}

const typeName = {
  1: 'aaa',
  2: 'bbb',
  3: 'ccc'
}

const FormModal: React.FC<IModalProps> = ({
  store,
}) => {
  const [form] = Form.useForm();

  useEffect(() => {
   //准备数据
  }, []);

  useEffect(() => {
    if (!store.modalVisible) {
        // 关闭重置
      form.resetFields();
    } else {
      if (store.current) {
        form.setFieldsValue({
          ...store.current,
        });
      }
    }
  }, [store.modalVisible]);

  const handleSelectChange = (value: any, name: any) => {
    //   获取当前选择数据
    const currentInfo = store.dataInfo?.find(v => v.id === value.value) || {};
    const inGroups = form.getFieldValue('inGroups');
    inGroups[name[0]].conGroup[name[1]] = {
      chooseId: value.value,
      // 可以加入选择值以外的其他属性
      xxx: currentInfo?.xxx,
      yyy: currentInfo?.yyy,
    };
    form.setFieldsValue({
      inGroups,
    });
  };


//   动态更新form表单,可以根据type类型显示不同控件
  const handleTypeChange = (value: any, name: any) => {
    const inGroups = form.getFieldValue('inGroups');
    inGroups[name[0]].conGroup[name[1]] = {
      ...inGroups[name[0]].conGroup[name[1]], // 合并之前的值,在更新
      type: value.value,
    };
    form.setFieldsValue({
      inGroups,
    });
  };

//   动态判断显示时间控件
  const handleTimeChange = (value: any, name: any) => {
    const inGroups = form.getFieldValue('inGroups');
    inGroups[name[0]].conGroup[name[1]] = {
      ...inGroups[name[0]].conGroup[name[1]],
      startDateTimeValue: value,
    };
    form.setFieldsValue({
      inGroups,
    });
  };

//   动态判断显示时间区间控件
  const handleTimeRangeChange = (value: any, name: any) => {
    const inGroups = form.getFieldValue('inGroups');
    inGroups[name[0]].conGroup[name[1]] = {
      ...inGroups[name[0]].conGroup[name[1]],
      startDateTimeValue: value?.[0],
      endDateTimeValue: value?.[1],
    };
    form.setFieldsValue({
      inGroups,
    });
  };

//   提交
  const handleFormSumbit = (values: any) => {
    const params = {
      ...values,
    }
    if (store.current) {
      params.id = store.current?.id;
    }
    // 提交接口
  };

  const handleShowType = (conditionType: any, anyType: any) => {
    let typeInfo = 1;
 //判断类型
    return typeInfo
  };

  const handleCancel = () => {
    //关闭弹窗,清除数据
  };



  return (
    <Modal
      width={1000}
      visible={modalVisible}
      title="新建多层嵌套组Form"
      onOk={form.submit}
      onCancel={handleCancel}
      confirmLoading={store.loading}
    >
      <Form form={form} onFinish={handleFormSumbit}>
        <Form.Item label="多层嵌套组Form">
          <Form.List name="inGroups">
            {(fields, { add, remove }) => (
              <div className={styles.form__item__rules}>
                {fields.length > 0 && <div className={styles.form__or}></div>}
                {fields.map((field, index) => (
                  <div className={styles.form__item__children} key={field.key}>
                    <Form.Item noStyle shouldUpdate>
                      {() => (
                        <>
                          <Form.Item
                            {...field}
                            noStyle
                            name={[field.name, 'name']}
                            fieldKey={[field.fieldKey, 'name']}
                          >
                            <Form.List name={[field.name, 'conGroup']}>
                              {(fieldsInside, { add: addInside, remove: removeInside }) => (
                                <div className={styles.form__children__rules__container}>
                                  {fieldsInside.length > 0 && (
                                    <div className={styles.form__or}></div>
                                  )}

                                  {fieldsInside.map(fieldInside => (
                                    <div
                                      className={styles.form__children__rules}
                                      key={fieldInside.key}
                                    >
                                      <Form.Item noStyle shouldUpdate>
                                        {() => (
                                          <Space>
                                            <Form.Item
                                              {...fieldInside}
                                              name={[fieldInside.name, 'chooseId']}
                                              fieldKey={[fieldInside.fieldKey, 'chooseId']}
                                              rules={[{ required: true, message: '请选择' }]}
                                            >
                                              <Select
                                                placeholder="请选择"
                                                showSearch
                                                optionFilterProp="label"
                                                onChange={(_e, item) =>
                                                  handleSelectChange(item, [
                                                    field.name,
                                                    fieldInside.name,
                                                  ])
                                                }
                                                style={{ width: '200px' }}
                                              >
                                                {store.dataInfo?.map((item: any) => (
                                                  <Select.Option
                                                    type={item.type}
                                                    label={item.name}
                                                    value={item.id}
                                                    key={item.id}
                                                  >
                                                    {item.name}
                                                  </Select.Option>
                                                ))}
                                              </Select>
                                            </Form.Item>
                                            <Form.Item
                                              {...fieldInside}
                                              name={[fieldInside.name, 'type']}
                                              fieldKey={[fieldInside.fieldKey, 'type']}
                                              rules={[
                                                { required: true, message: '请选择' },
                                              ]}
                                            >
                                              <Select
                                                showSearch
                                                optionFilterProp="label"
                                                placeholder="请选择"
                                                style={{ width: '100px' }}
                                                onChange={(_e, item) =>
                                                  handleTypeChange(item, [
                                                    field.name,
                                                    fieldInside.name,
                                                  ])
                                                }
                                              >
                                                {
                                                  (
                                                    INTENTION_VAR[
                                                    handleShowType(
                                                      store.mapData[form.getFieldValue('inGroups')[field.name]
                                                        ?.conGroup[fieldInside.name]?.chooseId]?.type,
                                                      store.mapData[form.getFieldValue('inGroups')[field.name]
                                                        ?.conGroup[fieldInside.name]?.chooseId]?.anyType
                                                    )
                                                    ] || []
                                                  ).map((item: { key: string; value: string }) => (
                                                    <Select.Option
                                                      key={item.key}
                                                      label={item.value}
                                                      value={item.key}
                                                    >
                                                      {item.value}
                                                    </Select.Option>
                                                  ))}
                                              </Select>
                                            </Form.Item>
                                            {/* 时间区间 */}
                                            {
                                             (form.getFieldValue('inGroups')[field.name]
                                             ?.conGroup[fieldInside.name]?.type === '条件类型') 
                                              && (
                                                <Form.Item
                                                  {...fieldInside}
                                                  name={[fieldInside.name, 'startDateTime']}
                                                  fieldKey={[fieldInside.fieldKey, 'startDateTime']}
                                                  rules={[
                                                    { required: true, message: '请选择时间' },
                                                  ]}
                                                initialValue={[moment(form.getFieldValue('inGroups')[field.name]
                                                ?.conGroup[fieldInside.name]?.startDateTimeValue, 'YYYY-MM-DD'), moment(form.getFieldValue('inGroups')[field.name]
                                                ?.conGroup[fieldInside.name]?.endDateTimeValue, 'YYYY-MM-DD')]}
                                                >
                                                  <RangePicker
                                                    format={'YYYY-MM-DD'}
                                                    onChange={(_e, item) =>
                                                      handleTimeRangeChange(item, [
                                                        field.name,
                                                        fieldInside.name,
                                                      ])
                                                    }
                                                  />
                                                </Form.Item>
                                              )}
                                            {/* 时间大于小于 */}
                                            {
                                              (
                                                (form.getFieldValue('inGroups')[field.name]
                                                  ?.conGroup[fieldInside.name]?.type === '条件类型') 
                                              )
                                              && (
                                                <Form.Item
                                                  {...fieldInside}
                                                  name={[fieldInside.name, 'startDateTime']}
                                                  fieldKey={[fieldInside.fieldKey, 'startDateTime']}
                                                  rules={[
                                                    { required: true, message: '请选择时间' },
                                                  ]}
                                                initialValue={moment(form.getFieldValue('inGroups')[field.name]
                                                ?.conGroup[fieldInside.name]?.startDateTimeValue || '', 'YYYY-MM-DD')}
                                                >
                                                  <DatePicker
                                                    format={'YYYY-MM-DD'}
                                                    onChange={(_e, item) =>
                                                      handleTimeChange(item, [
                                                        field.name,
                                                        fieldInside.name,
                                                      ])
                                                    }
                                                  />
                                                </Form.Item>
                                              )}
                                            {
                                             (form.getFieldValue('inGroups')[field.name]
                                             ?.conGroup[fieldInside.name]?.type === '条件类型') 
                                              && (
                                                <Form.Item
                                                  {...fieldInside}
                                                  name={[fieldInside.name, 'selectedValue']}
                                                  fieldKey={[fieldInside.fieldKey, 'selectedValue']}
                                                  rules={[
                                                    { required: true, message: '请选择' },
                                                  ]}
                                                >
                                                  <Select
                                                    showSearch
                                                    optionFilterProp="label"
                                                    placeholder="请选择"
                                                  >
                                                    {store.mapData[
                                                      form.getFieldValue('inGroups')[field.name]
                                                        ?.conGroup[fieldInside.name]?.chooseId
                                                    ]?.tagValueDTOS?.map(item => (
                                                      <Select.Option
                                                        label={item.tagValue}
                                                        value={item.id}
                                                        key={item.id}
                                                      >
                                                        {item.tagValue}
                                                      </Select.Option>
                                                    ))}
                                                  </Select>
                                                </Form.Item>
                                              )}
                                              {/* 动态判断 */}
                                            {(
                                             (form.getFieldValue('inGroups')[field.name]
                                             ?.conGroup[fieldInside.name]?.type === '条件类型') 
                                            ) && (
                                                <Form.Item
                                                  {...fieldInside}
                                                  name={[fieldInside.name, 'textValue']}
                                                  fieldKey={[fieldInside.fieldKey, 'textValue']}
                                                  rules={[
                                                    { required: true, message: '请输入' },
                                                  ]}
                                                >
                                                  <Input placeholder="请输入" />
                                                </Form.Item>
                                              )}
                                          </Space>
                                        )}
                                      </Form.Item>
                                      <div className={styles.form__var__close}>
                                        <img
                                          onClick={() => removeInside(fieldInside.name)}
                                          src={icon_del}
                                          alt=""
                                        />
                                      </div>
                                    </div>
                                  ))}
                                  {(!form.getFieldValue('inGroups')[field.name]?.conGroup
                                    ?.length ||
                                    form.getFieldValue('inGroups')[field.name]?.conGroup
                                      ?.length < 10) && (
                                      <div className={styles.form__item__tool}>
                                        <a
                                          className={styles.form__item__add}
                                          onClick={() => addInside()}
                                        >
                                          <img src={ICON.icon_add_blue} />
                                          新增子条件
                                        </a>
                                        <a
                                          className={styles.variable__del}
                                          onClick={() => remove(index)}
                                        >
                                          删除
                                        </a>
                                      </div>
                                    )}
                                </div>
                              )}
                            </Form.List>
                          </Form.Item>
                        </>
                      )}
                    </Form.Item>
                  </div>
                ))}
                {
                 <div className={styles.form__btn} onClick={() => add()}>
                    <img src={ICON.icon_add_green} />
                    新增条件
                  </div>
                }
              </div>
            )}
          </Form.List>
        </Form.Item>
       
      </Form>
    </Modal>
  );
};

export default FormModal;
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
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; ```
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值