Ant Design 动态增减form表单,第二三项根据第一项选中内容动态展示内容

效果图:
在这里插入图片描述

选中第一项下拉框,第二第三项展示在这里插入图片描述
点击添加条件,第二条仍然只展示第一项select框
在这里插入图片描述

后端返回数据格式:

ruleList:[
	{name:'通话时长',key:'TALK_TIME',type:’INT‘,unitName:'秒',
		operaObj:[{name:'>=',value:'>='},{name:'<=',value:'<='}],
		restrValues:null
	},
	{name:'是否成功',key:'IS_SUCCESS',type:’BOOLEAN‘,unitName:'',
		operaObj:[{name:'=',value:'='}],
		restrValues:[{name:'是',value:true},{name:'否',value:false}]
	},
	{name:'通话状态',key:'CALL_STATUS',type:’MULTI_SELECT‘,unitName:'',
		operaObj:[{name:'=',value:'in'}],
		restrValues:[{name:'黑名单',value:’1‘},{name:'忙碌',value:’2‘}]
	}
]

根据选中的第一项,动态展示第二项第三项,以及第三项的类型是下拉框还是input,和单位unitName
代码:

import { ModalForm } from '@ant-design/pro-form';
import type { FormInstance } from 'antd';

const manageFormRef = useRef<FormInstance>();
const [formData, setFormDate] = useState({
	ruleConditionDTOList: [null]
});


<ModalForm
	title='添加'
	// 弹窗开关,跟目前主要所写逻辑无关,可以先不管,按照你自己的弹窗开关事件即可
    open={visible}
    width={650}
    formRef={manageFormRef}
    layout='vertical'
    autoComplete='off'
    labelCol={{ span: 12 }}
    onFieldsChange={() => setFormDate(manageFormRef.current?.getFieldValue())}
    // 默认初始化值
    initialValues={
    	{
        	isAddToBlacklist: false,
            ruleConditionDTOList: [{}]
         }
    }
    // 弹窗关闭
    onOpenChange={onClose}
    // 提交表单
    onFinish={handleOnFinish}
>
<Form.Item label='同时满足以下条件'>
	<Form.List name="ruleConditionDTOList">
    	{(fields, { add, remove }) => (
        	<>
            	{fields.map((field, index) => (
                	<Space key={field.key} style={{ display: 'flex', flexWrap: 'wrap', marginBottom: 8 }} align="baseline">
                    	<Form.Item
                        	name={[field.name, 'key']}
                            rules={[{ required: true, message: '请选择条件' }]}
                       	>
                        <Select
                        	placeholder="请选择条件"
                            style={{ width: 200 }}
                            onChange={(val) => handleChange(val, field, index)}
                        >
                        	{ruleList && ruleList.map((item: any) => (
                            	<Select.Option value={item.key} fieldNames={item}>{item.name}</Select.Option>
                             ))}
                         </Select>
                     </Form.Item>
					// 第一项有值,显示第二项
                    {formData?.ruleConditionDTOList[index]?.key && 			<Form.Item

                     	name={[field.name, 'operator']}
                        rules={[{ required: true, message: '请选择' }]}
                    >
                    	<Select style={{ width: 100 }} placeholder="请选择">
                        	{ruleList && ruleList.find(v => formData.ruleConditionDTOList[index].key == v.key)?.operaObj.map((item: any) => (
                             	<Select.Option value={item.value}>{item.name}</Select.Option>
                            ))}
                        </Select>
                    </Form.Item>
                	}
                	// 第一项有值,展示第三项,根据第一项的type,动态展示第三项是input或是select或是多选,我这里写了个函数
                	{formData?.ruleConditionDTOList[index]?.key && getModel(formData?.ruleConditionDTOList[index]?.key, field, index)}
                	// form表单组的长度大于1,显示删除按钮,否则隐藏
                	{fields.length > 1 &&
                		<DeleteOutlined
                    		style={{ color: 'rgb(43, 132, 255)' }}
                        	className="dynamic-delete-button"
                        	onClick={() => remove(field.name)}
                     	/>}
                	</Space>
                ))}
            	<Form.Item>
            		<Button style={{ width: '100px' }} type="primary" onClick={() => add()} block>添加条件</Button>
            	</Form.Item>
            </>
        )}
     </Form.List>
</Form.Item>
</ModalForm>

// 根据type类型动态展示第三项要展示的内容
const getModel = (key: any, field: any, index: Number) => {
        const item = ruleList.find((v: any) => v.key == key);
        const types = {
            INT: (field: any, item: any) => {
                return <Form.Item
                    name={[field.name, 'value']}
                    rules={[{ required: true, message: '请输入' }]}
                >
                    <Input placeholder="请输入" style={{ width: 100 }} suffix={item.unitName} />
                </Form.Item>
            },
            // 多选下拉
            MULTI_SELECT: (field: any, item: any) => {
                return <Form.Item
                    name={[field.name, 'value']}
                    rules={[{ required: true, message: '请选择' }]}
                >
                    <Select mode="multiple" style={{ width: 200 }}>
                        {item.restrValues.map((v: any) => (
                            <Select.Option value={v.value}>{v.name}</Select.Option>
                        ))}
                    </Select>
                </Form.Item>
            },
            BOOLEAN: (field: any, item: any) => {
                return <Form.Item
                    name={[field.name, 'value']}
                    rules={[{ required: true, message: '请选择' }]}
                >
                    <Select style={{ width: 100 }}>
                        {item.restrValues.map((v: any) => (
                            <Select.Option value={v.value}>{v.name}</Select.Option>
                        ))}
                    </Select>
                </Form.Item>
            }

        }
        return types[item.type](field, item, index) ?? null;
    },
    // 选中第一项第二三项清空
    const handleChange = (val: any, field: any, index: any) => {
        const { ruleConditionDTOList } = formData
        ruleConditionDTOList[index] = Object.assign(ruleConditionDTOList[index] ?? {}, {
            key: val,
            operator: null,
            value: undefined
        })
        manageFormRef.current?.setFieldValue('ruleConditionDTOList', ruleConditionDTOList);
        setFormDate(manageFormRef.current?.getFieldValue());
        console.log(manageFormRef.current?.getFieldValue(), '置空');
    }


// 编辑时数据回显,后端返回的数据

data:{
	ruleConditionDTOList:[
		{name:'通话状态',key:'CALL_STATUS',type:'MULTI_SELECT',operator:'in',unitName:'',value:'1,2'},
		{name:'通话时长',key:'TALK_TIME',type:'INT',operator:'>=',unitName:'秒'}
	]
}

回显

useEffect(()=>{
	// 点击编辑,传的tagData单行row
	if(tagData){
		// 由于我获取接口都是异步,赋值时需要setTimeout一下
		setTimeout(() => {
                const { ruleConditionDTOList: list } = tagData
                let arr:any = []
                list?.map((v:any) => {
                	// 写个辅助函数,根据不同type,对value进行不同的操作
                    const getValue = (type: any) => {
                        const types = {
                            INT: () => {
                                return v.value
                            },
                            BOOLEAN: () => {
                                return Boolean(v.value)
                            },
                            MULTI_SELECT: () => {
                                const value = v?.value.split(',')
                                return value
                            }
                        }
                        return types[type]() ?? ''
                    }
                    const object = {
                        name: v.name,
                        key: v.key,
                        operator: v.operator,
                        value: getValue(v.type),
                        type: v.type,
                        unitName: v.unitName
                    }
                    arr.push(object)
                })
                manageFormRef.current?.setFieldsValue({
                    ruleConditionDTOList: arr
                })
                setFormDate(manageFormRef.current?.getFieldsValue())
            }, 300);
	}
},[tagData])

提交数据部分就不写了,提交跟接口相对应的数据就行

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/659261.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

[JAVASE] String类 StringBuffer类 StringBuilder类

目录 一.String类 1.1 String字符串不可变的原因 1.2 字符串中的比较方法 1.2.1 equals 1.2.2 compareTo 与 compareToIgnoreCase 1.3 字符串中的查找方法 1.3.1 charAt 1.3.2 indexOf 与 lastIndexOf 1.4 字符串中的转换方法 1.4.1 valueOf 1.4.2 toUpperCase 与 to…

msi安装mysql8 启动失败,提示只有在任务处于完成状态(RanToCompletion、Faulted 或 Canceled)时才能释放它。

解决方案: 1.打开服务,找到安装的mysql 2. 右击&#xff0c;打开属性&#xff0c;进入【登录】选项卡&#xff0c;选择本地系统账户。 3. 点击确定-->应用 4.服务中选择开始服务 5.服务启动成功后,在安装步骤中继续点击执行

熵值法(熵权法)

熵值法&#xff08;Entropy Method&#xff09;是一种多属性决策分析方法&#xff0c;主要用于权重确定、排序和评价。它在风险评估、资源配置、环境管理等领域得到广泛应用。熵值法的核心思想是基于信息熵的概念&#xff0c;利用信息熵来度量各属性对决策的贡献程度&#xff0…

串口环保212设备 转 profinet IO协议项目案例

1 文档说明 数采仪通过串口输出环保212的数据&#xff0c;vfbox网关通过串口采集数采仪的数据。网关把采集的数据转换成Profinet IO从站数据。 2 测试数采仪的串口数据 测试数采仪的串口有数据输出&#xff0c;并且需要知道输出的数据内容。 把数采仪的串口&#xff08;232或…

【记录】打印|无需排版,生成证件照打印PDF,打印在任意尺寸的纸上(简单无损!)

以前我打印证件照的时候&#xff0c;我总是在网上找在线证件照转换或者别的什么。但是我今天突然就琢磨了一下&#xff0c;用 PDF 打印应该也可以直接打印出来&#xff0c;然后就琢磨出来了&#xff0c;这么一条路大家可以参考一下。我觉得比在线转换成一张 a4 纸要方便的多&am…

AI视频教程下载:ChatGPT API、HTML、CSS 和 JS开发AI聊天机器人

在课程中,你将开启一段令人兴奋的聊天机器人开发之旅,并装备自己创建智能对话代理所需的技能和知识。 利用 ChatGPT API、HTML、CSS 和 JavaScript 的强大功能,你将学习如何设计和构建吸引用户并提供个性化体验的聊天机器人界面。深入探讨聊天机器人开发的基础知识,了解对话设…

给转行产品经理的小白的一些建议

哈喽我是小源&#xff0c;毕业在教培大厂做了1年的班主任&#xff0c;下午1点上班&#xff0c;被优化后gap3月找到了自己的本命岗位——产品经理&#xff01; 其实这个转变也挺机缘巧合的&#xff0c;朋友和我都是教培行业&#xff0c;她是成人职教类&#xff0c;我是k111类&a…

SWM181系列应用

一、SWM181系列 ISP功能 1.1、注意&#xff1a;ISP引脚为B0&#xff0c;VCC&#xff0c;GND是UART-RX、UART-TX 下载引脚。所有型号的UART-RX - - > A0&#xff0c;UART-TX - - > A1。 1.2、注意&#xff1a;板级设计必须留出ISP引脚&#xff0c;防止调试过程中芯片锁死后…

Java——执行流程

一、执行流程 1、示例 //第一个Java程序 public class Hello{public static void main(String[] args){System.out.println("Hello World!");} } 编译&#xff1a; 执行&#xff1a; 我们可以看到这里的是类名&#xff0c;而不是字节码文件名 Hello.class &#…

Android manifest清单文件意外权限来源和合并规则

问题背景 当自写APP发现无缘无故多申请了多个权限,其中一个就是:android.permission.WAKE_LOCK. 一想就知道如果并非自己在APP main中引入的,那就是依赖的库清单文件导入进来的. 定位问题 定位手段 1.manifest-merger-buildVariant-report.txt 根据其内容可知, WAKE_LOCK 权…

分布式专题

一&#xff1a;分布式事务 1、理论基础 分布式事务主要区分本地事务 什么是本地事务&#xff08;Local Transaction&#xff09;&#xff1f;本地事务也称为数据库事务或传统事务&#xff08;相对于分布式事务而言&#xff09;。尤其对于数据库而言&#xff0c;为了数据安全…

图形学初识--矩阵和向量

文章目录 前言正文向量什么是向量&#xff1f;向量涉及哪些常见计算&#xff1f;1、取模2、归一化3、向量加法4、向量减法5、向量与标量乘6、向量点乘&#xff08;内积&#xff09;7、向量投影 向量有哪些基本应用&#xff1f; 矩阵什么是矩阵&#xff1f;矩阵涉及哪些常见计算…

【数据结构】冒泡排序、直接插入排序、希尔排序详解!

文章目录 1. 冒泡排序&#x1f34e;2. 直接插入排序&#x1f34e;3. 希尔排序&#xff08;缩小增量排序&#xff09;&#x1f34e; 1. 冒泡排序&#x1f34e; &#x1f427; 基本思想&#xff1a; 比较相邻的元素。如果第一个比第二个大&#xff0c;就交换他们两个。 大的数据…

使用docker部署项目

一、docker私有镜像仓库 1、docker私有镜像仓库 库&#xff08;Repository&#xff09;是集中存放镜像的地方&#xff0c;又分为公共镜像和私有仓库。 当我们执行docker pull xxx的时候&#xff0c;它实际上是从registry.docker.com这个地址去查找&#xff0c;这就是Docker公…

基于稀疏辅助信号平滑的心电信号降噪方法(Matlab R2021B)

基于形态成分分析理论&#xff08;MCA&#xff09;的稀疏辅助信号分解方法是由信号的形态多样性来分解信号中添加性的混合信号成分&#xff0c;它最早被应用在图像处理领域&#xff0c;后来被引入到一维信号的处理中。 在基于MCA稀疏辅助的信号分析模型中&#xff0c;总变差方…

交互设计如何助力传统技艺在当代复兴?

背景介绍 榫卯是中国传统木工中一种独特的接合技术&#xff0c;它通过构件间的凸凹部分相互配合来实现两个或多个构件的紧密结合。这种结构方式不依赖于钉子或其他金属连接件&#xff0c;而是利用木材自身的特性&#xff0c;通过精巧的设计和工艺&#xff0c;实现构件间的稳定…

【MAC】Spring Boot 集成OpenLDAP(含本地嵌入式服务器方式)

目录 一、添加springboot ldap依赖&#xff1a; 二、本地嵌入式服务器模式 1.yml配置 2.创建数据库文件&#xff1a;.ldif 3.实体类 4.测试工具类 5.执行测试 三、正常连接服务器模式 1.yml配置 2.连接LDAP服务器配置类&#xff0c;初始化连接&#xff0c;创建LdapTem…

Android framework修改,禁止指定包名的apk安装到设备上(基于Android10.0.0-r41)

文章目录 Android framework修改&#xff0c;禁止指定包名的apk安装到设备上(基于Android10.0.0-r41)1.新增接口提供给上层调用2.在pms中实现新增的接口3.找到preparePackageLI方法。4.测试验证 Android framework修改&#xff0c;禁止指定包名的apk安装到设备上(基于Android10…

如何利用短链接巧妙避开多渠道推广大坑

在当下&#xff0c;推广渠道多样化对企业来说&#xff0c;那可是机遇与大坑并存&#xff01;多渠道推广的重要性大家都懂&#xff0c;但为啥说有坑呢&#xff1f;一旦企业开启多渠道推广模式&#xff0c;就得面对大量人力物力的投入&#xff0c;可要是区分不了各个渠道的推广效…

超详细介绍基于微调 Faster R-CNN实现海上航拍图像中检测小物体-含源码与数据集免费下载

在航拍图像中检测小物体,尤其是对于海上救援等关键应用而言,是一项独特的挑战。及时检测水中的人可能意味着生死之间的差别。我们的研究重点是微调 Faster R-CNN(一种强大的两阶段物体检测器),以满足这一重要需求。 我们研究的核心是SeaDroneSee 数据集,这是一组重要的图…