vue3+arco design通过动态表单方式实现自定义筛选

目录

1.说明

2.示例

3.运行截图

​编辑 4.总结


1.说明

        (1) 本文主要实现通过动态表单的方式实现自定义筛选的功能,用户可以自己添加筛选的项目,筛选条件及筛选内容。

        (2) 每个项目的筛选包含筛选项目,筛选条件,筛选方式及筛选值。

                筛选项目代表表中的字段,如姓名,年龄等

                筛选条件包含等于,不等于,大于,小于,包含等

                筛选类型包含手动输入值的方式,通过下拉进行选择的方式,和表中的其他字段进行比较的方式

                筛选值可以手动输入,可以通过下拉进行选择,也可以选择某个日期。

2.示例

<template>
  <a-modal :visible="visibleFlag" @ok="handleOk" @cancel="handleCancel" unmountOnClose width="auto">
    <div style="text-align: right">
      <a-button @click="handleAdd()">Add</a-button>
    </div>
    <a-form :model="form" layout='vertical' style="width: 1000px;height: 400px;" ref="formRef">
      <div v-for="(item,index) in form.data">
        <a-row :gutter="10">
          <a-col :span="5">
            <a-form-item :field="`data[${index}].filterColumn`" label="Column" :hide-label="index != 0"
                         :rules="[{required:true,message:'Column不能为空'}]"
                         validate-trigger="blur">
              <a-select v-model="item.filterColumn" :style="{width:'500px'}" placeholder="Please select ..."
                        @blur="columnBlur(form.data[index].filterColumn, form.data[index].filterType , index)" allow-clear>
                <a-option v-for="item of columns" :value="item.value" :label="item.label"/>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :span="6">
            <a-form-item :field="`data[${index}].filterOperation`" label="Operation" :hide-label="index != 0"
                         :rules="[{required:true,message:'Operation不能为空'}]"
                         validate-trigger="blur">
              <a-select v-model="item.filterOperation" :style="{width:'500px'}"
                        placeholder="Please select ..." allow-clear>
                <a-option v-for="item of filterOpeData[index]" :value="item.value" :label="item.label"/>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :span="5">
            <a-form-item :field="`data[${index}].filterType`" label="Type" :hide-label="index != 0"
                         :rules="[{required:true,message:'Type不能为空'}]"
                         validate-trigger="blur">
              <a-select v-model="item.filterType" :style="{width:'500px'}" placeholder="Please select ..."
                        @blur="typeBlur(form.data[index].filterColumn, form.data[index].filterType, index)" allow-clear>
                <a-option v-for="item of filterTypeData" :value="item.value" :label="item.label"/>
              </a-select>
            </a-form-item>
          </a-col>
          <a-col :span="5">
            <a-form-item :field="`data[${index}].filterValue`" label="Value" :hide-label="index != 0"
                         :rules="[{required:true,message:'Value不能为空'}]"
                         validate-trigger="blur">
              <a-input v-model="item.filterValue" :style="{width:'500px'}"
                       placeholder="Please enter something"
                       allow-clear v-if="valueFlag[index] == 0"/>
              <a-select v-model="item.filterValue" :style="{width:'400px'}" placeholder="Please select ..."
                        v-if="valueFlag[index] == 1" allow-clear>
                <a-option v-for="item of colValList[index]" :value="item.value" :label="item.label"/>
              </a-select>
              <a-date-picker v-model="item.filterValue" :style="{width:'400px'}"
                             v-if="valueFlag[index] == 2" />
            </a-form-item>
          </a-col>
          <a-col :span="3">
            <a-button v-show="index != 0" @click="handleDelete(index)" :style="{marginLeft:'10px'}">Delete</a-button>
          </a-col>
        </a-row>
      </div>
    </a-form>
  </a-modal>
</template>

<script lang="ts" setup>
import {onMounted, ref} from 'vue';
import {Message} from '@arco-design/web-vue';
import {FormInstance} from '@arco-design/web-vue/es/form';


const formRef = ref<FormInstance>();
const visibleFlag = ref(false)

// 0:输入框;1:下拉选择器;2:日期
const valueFlag = ref([] as any)
valueFlag.value.push(0)

const form = ref({
  data: [{
    filterColumn: '',
    filterOperation: '',
    filterType: '',
    filterValue: ''
  }]
})

const colValList = ref([] as any)

const filterOpeData = ref([] as any)

const filterTypeData = [{
  value: '0',
  label: 'Value',
}, {
  value: '1',
  label: 'Column',
}, {
  value: '2',
  label: 'User List',
}]

const operationData1 = [
  {value: '1', label: 'EQUAL'},
  {value: '2', label: 'GREATER_THAN'},
  {value: '3', label: 'GREATER_THAN_OR_EQUAL'},
  {value: '4', label: 'LESS_THAN'},
  {value: '5', label: 'LESS_THAN_OR_EQUAL'},
  {value: '6', label: 'NOT_EQUAL'}]
const operationData2 = [
  {value: '1', label: 'EQUAL'},
  {value: '2', label: 'GREATER_THAN'},
  {value: '3', label: 'GREATER_THAN_OR_EQUAL'},
  {value: '4', label: 'LESS_THAN'},
  {value: '5', label: 'LESS_THAN_OR_EQUAL'},
  {value: '6', label: 'NOT_EQUAL'},
  {value: '9', label: 'CONTAINS'},
  {value: '10', label: 'STARTS_WITH'},
  {value: '11', label: 'ENDS_WITH'},
  {value: '12', label: 'DOES_NOT_START_WITH'},
  {value: '13', label: 'DOES_NOT_END_WITH'},
  {value: '14', label: 'DOES_NOT_CONTAIN'},
  {value: '15', label: 'STARTS_OR_ENDS_WITH'}
]

const handleOk = async () => {
  const validRes = await formRef.value?.validate();
  if (!validRes) {
    visibleFlag.value = false;
    console.log(JSON.stringify(form.value.data))
  } else {
    console.log("校验失败")
  }
}

const handleCancel = () => {
  visibleFlag.value = false;
}

const handleDelete = (index: any) => {
  form.value.data.splice(index, 1);
  valueFlag.value.splice(index, 1);
  colValList.value.splice(index, 1);

}

const handleAdd = () => {
  form.value.data.push({
    filterColumn: '',
    filterOperation: '',
    filterType: '',
    filterValue: ''
  })
  valueFlag.value.push(0)
}

const columnBlur = (colVal: any, typeVal: any, index: any) => {
  if (!colVal) {
    return
  }
  const col = columns.value.find((item: { value: any; }) => item.value == colVal)
  if (col.type == 'text' || col.type == 'number') {
    filterOpeData.value[index] = operationData2
  } else {
    filterOpeData.value[index] = operationData1
  }
  if (col.type == 'list' && typeVal != '1') {
    valueFlag.value[index] = 1
    colValList.value[index] = [{
      value: '1',
      label: '处理提交'
    }, {
      value: '2',
      label: '处理中'
    }, {
      value: '3',
      label: '处理完成'
    }]
  }
  if (col.type == 'date') {
    valueFlag.value[index] = 2
  }
}

const typeBlur = (colVal: any, typeVal: any, index: any) => {
  if (typeVal == '1') {
    if (!colVal) {
      Message.error({content: 'column信息不能为空', position: 'top'});
      return
    } else {
      const col = columns.value.find((item: { value: any; }) => item.value == colVal)
      if (col.type == 'list') {
        Message.error({content: 'list类型的column不支持和其他列进行比较', position: 'top'});
        form.value.data[index].filterType = ''
        return
      }
      valueFlag.value[index] = 1
      if (col.type == 'date') {
        colValList.value[index] = columns.value.filter((item: { type: string; }) => item.type == 'date')
      } else if (col.type == 'text') {
        colValList.value[index] = columns.value.filter((item: { type: string; }) => item.type == 'text' || item.type == 'number')
      } else if (col.type == 'number') {
        colValList.value[index] = columns.value.filter((item: { type: string; }) => item.type == 'number')
      } else if (col.type == 'list') {
      } else {
        colValList.value[index] = []
      }
    }
  }

}

// 打开弹窗
const openDialog = () => {
  visibleFlag.value = true;
};
// 导出方法在父组件中进行使用
defineExpose({openDialog});

const columns = ref()
const getColumnList = () => {
  columns.value = [{
    value: '12',
    label: 'genoId',
    type: 'text'
  },
    {
      value: '13',
      label: 'status',
      type: 'list'
    },
    {
      value: '14',
      label: 'createTime',
      type: 'date'
    },
    {
      value: '15',
      label: 'qty',
      type: 'number'
    }
  ]
}

// 组件完成初始渲染并创建 DOM 节点后运行
onMounted(async () => {
  await getColumnList()
})

</script>

<script lang="ts">
export default {
  name: "dynamicFilter"
}
</script>

<style scoped>

</style>

 说明:

        ①通过表单的方式进行实现,表单关联的数据源form是对象格式,如下:

const form = ref({
  data: [{
    filterColumn: '',
    filterOperation: '',
    filterType: '',
    filterValue: ''
  }]
})

       对象内是一个id为data的数组,数组内的每条数组则存储一个项目的筛选内容,包含筛选项目,筛选条件,筛选方式及筛选值。数据源设置为对象是为了进行校验处理,如果是数组格式,无法实现动态表单的的校验(不同的前端框架,可能会有所不同,但推荐使用对象格式)

        ②动态表单的实现
        在form标签内嵌套div标签,并在div标签上进行循环form.data,如果动态的项目只有一个,可以直接在form-item上进行循环处理。具体的每个表单项可以通过form.data[index].表单项名的方式进行绑定,也可以通过item.表单项名的方式进行绑定。点击新增按钮,会向form.data中push一条新数据,添加的筛选项目后面有删除按钮,点击删除按钮,通过form.data.splice方法删除数组中的元素。

        ③动态表单的校验处理

        在每个表单项中添加校验规则,不要在form上添加校验规则

        在arco design框架中的动态表单校验如下:

            <a-form-item :field="`data[${index}].filterColumn`" label="Column" :hide-label="index != 0"
                         :rules="[{required:true,message:'Column不能为空'}]"
                         validate-trigger="blur">
              <a-select v-model="item.filterColumn" :style="{width:'500px'}" placeholder="Please select ..."
                        @blur="columnBlur(form.data[index].filterColumn, form.data[index].filterType , index)" allow-clear>
                <a-option v-for="item of columns" :value="item.value" :label="item.label"/>
              </a-select>
            </a-form-item>

 通过rules关联校验规则,注意field属性的设置,field属性主要要用来关联校验的项目,尤其在动态表单时,校验项目是变化的,要通过下标进行绑定,在arco design中field需要进行如上设置,结果例如:data[0].filterColumn。

在arco design中是设置field属性,在element ui中是设置prop属性,并且内容的设置方式也不一样,这点一定要注意。

        ④提交时的校验

        当前表单嵌套在对话框中,点击确定按钮时,需要先进行表单的校验处理,如下:

const handleOk = async () => {
  const validRes = await formRef.value?.validate();
  if (!validRes) {
    visibleFlag.value = false;
    console.log(JSON.stringify(form.value.data))
  } else {
    console.log("校验失败")
  }
}

通过调用表单的ref对象的validate方法,如果校验失败则返回失败的项目的field属性内容及错误信息,如果成功则返回undefined,所以通过判断返回结果就可以判断校验成功与否。 

校验失败的返回信息如下

{
	"data[0].filterColumn": {
		"label": "Column",
		"field": "data[0].filterColumn",
		"type": "string",
		"isRequiredError": true,
		"message": "Column不能为空"
	},
	"data[0].filterOperation": {
		"label": "Operation",
		"field": "data[0].filterOperation",
		"type": "string",
		"isRequiredError": true,
		"message": "Operation不能为空"
	},
	"data[0].filterType": {
		"label": "Type",
		"field": "data[0].filterType",
		"type": "string",
		"isRequiredError": true,
		"message": "Type不能为空"
	},
	"data[0].filterValue": {
		"label": "Value",
		"field": "data[0].filterValue",
		"type": "string",
		"isRequiredError": true,
		"message": "Value不能为空"
	},
	"data[1].filterColumn": {
		"label": "Column",
		"field": "data[1].filterColumn",
		"type": "string",
		"isRequiredError": true,
		"message": "Column不能为空"
	},
	"data[1].filterOperation": {
		"label": "Operation",
		"field": "data[1].filterOperation",
		"type": "string",
		"isRequiredError": true,
		"message": "Operation不能为空"
	},
	"data[1].filterType": {
		"label": "Type",
		"field": "data[1].filterType",
		"type": "string",
		"isRequiredError": true,
		"message": "Type不能为空"
	},
	"data[1].filterValue": {
		"label": "Value",
		"field": "data[1].filterValue",
		"type": "string",
		"isRequiredError": true,
		"message": "Value不能为空"
	},
	"data[2].filterColumn": {
		"label": "Column",
		"field": "data[2].filterColumn",
		"type": "string",
		"isRequiredError": true,
		"message": "Column不能为空"
	},
	"data[2].filterOperation": {
		"label": "Operation",
		"field": "data[2].filterOperation",
		"type": "string",
		"isRequiredError": true,
		"message": "Operation不能为空"
	},
	"data[2].filterType": {
		"label": "Type",
		"field": "data[2].filterType",
		"type": "string",
		"isRequiredError": true,
		"message": "Type不能为空"
	},
	"data[2].filterValue": {
		"label": "Value",
		"field": "data[2].filterValue",
		"type": "string",
		"isRequiredError": true,
		"message": "Value不能为空"
	}
}

校验通过后输出的form.data信息,如下:

[{
	"filterColumn": "12",
	"filterOperation": "1",
	"filterType": "0",
	"filterValue": "23"
}, {
	"filterColumn": "13",
	"filterOperation": "1",
	"filterType": "0",
	"filterValue": "1"
}, {
	"filterColumn": "14",
	"filterOperation": "2",
	"filterType": "0",
	"filterValue": "2024-05-14"
}]

3.运行截图

校验失败

输入内容后,校验通过

 4.总结

①注意表单绑定的数据源的格式及不同前端框架的校验的方式

②为了使画面更加友好,可以将表单放在表格中

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

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

相关文章

【算法】位运算算法——只出现一次的数字Ⅱ

题解&#xff1a;只出现一次的数字Ⅱ(位运算算法) 目录 1.题目2.题解&#xff1a;3.代码示例4.总结 1.题目 题目链接&#xff1a;LINK 要求&#xff1a;时间复杂度&#xff1a;O(N)&#xff0c;空间复杂度&#xff1a;O(1) 2.题解&#xff1a; 3.代码示例 class Solution {…

20212313 2023-2024-2 《移动平台开发与实践》第6次作业

20212313 2023-2024-2 《移动平台开发与实践》第6次作业 1.实验内容 设计并开发一个语音识别应用系统。 通过使用RecognizerIntent实现语音识别功能&#xff0c;开发一个Android语音识别系统。 2.实验过程 2.1下载语音识别的SDK 这里我们选择的是科大讯飞的语音识别&#…

2024年4月—马克思主义基本原理概论真题及答案解析(上海自考)

目录 1.选择题 2.简答题 3.论述题 1.选择题 2.简答题

aws glue配置读取本地kafka数据源

创建连接时填写本地私有ip地址&#xff0c;选择网络配置 配置任务选择kafka作为数据源 但是执行任务时日志显示连接失败 文档提到只能用加密通信 如果您希望与 Kafka 数据源建立安全连接&#xff0c;请选择 Require SSL connection (需要 SSL 连接)&#xff0c;并在 Kafka priv…

text-embedding 嵌入模型

为什么使用embedding 计算机只能处理数字&#xff0c;但我们希望它能够理解文字、图片或其他形式的数据。这就是embedding的作用。它将这些复杂的数据转换成数字表示&#xff0c;就像给它们贴上了标签一样。这些数字表示不仅保留了原始数据的重要信息&#xff0c;还能在计算机…

【OpenGL手册14】实例化

目录 一、说明 二、实例化 三、实例化数组 四、小行星带 五、完整代码 六、结论 一、说明 实例化渲染&#xff0c;是用少数数据做模板&#xff0c;实现海量物体渲染的手段方法。用实例化渲染&#xff0c;需要对每个实例产生一定描述数据。如何实现&#xff1f;请看本文下…

Vue3实战笔记(36)—粒子特效完成炫酷的404

文章目录 前言404特效总结 前言 昨天介绍了一个粒子特效小例子&#xff0c;不够直观&#xff0c;下面直接实战在自己的项目中实现一个好玩滴。 404特效 更改之前创建好的404.vue: <template><div class"container"><vue-particles id"tspartic…

EXCEL如何自动根据上行内容填充到空格

接上篇文章&#xff0c;经过宏命令后会有空格出现&#xff0c;那么如何自动根据上行内容填充到空格呢&#xff1f; 请看步骤~ ctrl G 选择空值–》定位 -》 按 -》然后等于上一行 -》ctrl enter 一。全选表格&#xff0c; ctrl G 调出界面&#xff0c;选择空值按下定位 …

二分答案思想下的二进制问题

序列合并 题目描述 给定一个长度为 n n n 的非负整数序列 { a n } \{a_n\} {an​}&#xff0c;你可以进行 k k k 次操作&#xff0c;每次操作你选择两个相邻的数&#xff0c;把它们合并成它们的按位或。 形式化地&#xff0c;一次操作中&#xff0c;你选择一个下标 i i …

Transformer模型架构笔记

0. 简介 Transformer是一种用于自然语言处理&#xff08;NLP&#xff09;和其他序列到序列&#xff08;sequence-to-sequence&#xff09;任务的深度学习模型架构&#xff0c;它在2017年由Vaswani等人首次提出。Transformer架构引入了自注意力机制&#xff08;self-attention …

windows中每日定时执行python脚本,解决问题

由于需要一个每天定时执行的任务&#xff0c;所以需要定时启动&#xff0c;网上看了很多方法&#xff0c;感觉不能在python脚本种写个while true 定时执行&#xff0c;占资源不说还不可靠。 最后考虑通过系统工具定时启动&#xff0c;发现linux中有crontab&#xff0c;windows…

JMH304-剑侠情缘2网络版+2017纹饰端+翅膀+单机+外网整理+各种副本

资源介绍&#xff1a; 藏剑-太虚-梁山-杀手堂种树地宫师门纹饰装备长流云阳套等等———– 做登录器联系站长 资源截图&#xff1a; 下载地址

2023、2024国赛web复现wp

2023 Unzip 类型&#xff1a;任意文件上传漏洞 主要知识点&#xff1a;软链接 随便上传一个一句话木马文件&#xff0c;得到一串php代码 根据代码上传zip文件发现进入后还是此页面 代码审计&#xff1a; <?php error_reporting(0); highlight_file(__FILE__);$finfo fin…

Mac免费软件推荐

1. iTerm2 - 功能强大的终端 iTerm2 是一个功能强大且灵活的终端仿真器&#xff08;可替代系统默认终端&#xff09;&#xff0c;适合需要在 macOS 上进行大量终端操作的用户。其丰富的功能和高可定制性使得 iTerm2 成为许多开发者和系统管理员的首选工具。无论是处理多个会话…

基于MyBatisPlus表结构维护工具

SuperTable表结构维护工具 一、简述 用于同步表实体与数据库表结构&#xff0c;同步建表、删改字段、索引&#xff0c;种子数据的工具… 一、开发环境 JDK&#xff1a;JDK8SpringBoot&#xff1a;2.7.2MyBatisPlus: 3.5.6MySQL: 5.7其他依赖&#xff1a;略 二、特性 表结…

5G工业数采网关的功能及工业应用-天拓四方

随着5G技术的不断发展&#xff0c;其在工业领域的应用日益广泛。5G工业数采网关作为连接工业设备与网络的重要枢纽&#xff0c;具备多种功能&#xff0c;为工业自动化、智能制造和智慧工厂提供了强大的支持。本文将详细解析5G工业数采网关的功能&#xff0c;并探讨其在工业领域…

【调试笔记-20240528-Linux-用 OpenWrt-23.05 SDK 编译 frp 软件包】

调试笔记-系列文章目录 调试笔记-20240528-Linux-用 OpenWrt-23.05 SDK 编译 frp 软件包 文章目录 调试笔记-系列文章目录调试笔记-20240528-Linux-用 OpenWrt-23.05 SDK 编译 frp 软件包 前言一、调试环境操作系统&#xff1a;Ubuntu 22.04.4 LTS编译环境调试目标 二、调试步…

剖析【C++】——类与对象(中)——小白篇—超详解

目录 1.类的6个默认成员函数&#xff1a; 1. 默认构造函数&#xff08;Default Constructor&#xff09; 2. 析构函数&#xff08;Destructor&#xff09; 3. 拷贝构造函数&#xff08;Copy Constructor&#xff09; 4. 拷贝赋值运算符&#xff08;Copy Assignment Operato…

【RK3288 Android10 T8pro usb hid-multitouch idc配置】

【RK3288 Android10 T8pro usb hid-multitouch idc配置】 文章目录 【RK3288 Android10 T8pro usb hid-multitouch idc配置】背景代码分析1. 读取配置文件2. 标志内外置屏幕3. 设置输入设备4. findviewport()5. 根据对应的viewport来计算相应的mapping的参数 结论 背景 T8pro …

C++网络编程——socket

在服务器中&#xff0c;需要建立一个socket套接字才能对外提供一个网络通信接口&#xff0c;在Linux系统中套接字仅是一个文件描述符&#xff0c;也就是一个int类型的值 socket概念 socket 的原意是“插座”&#xff0c;在计算机通信领域&#xff0c;socket 被翻译为“套接字…