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

news2024/11/26 18:52:48

目录

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属性的设置,在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.总结

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用 OpenCV 创建视频(74)

返回:OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 上一篇:OpenCV 库来捕获和处理视频输入和相似度测量(73) 下一篇 :OpenCV系列文章目录&#xff08;持续更新中......&#xff09; 目标 每当您使用视频源时&#xff0c;您最终可能希望将图像处理结果保存为…

HDLC协议

目录 1.概念 2.配置 3.HDLC帧结构 4.HDLC帧类型 1.概念 HDLC(High-level Data Link Control&#xff09;高级数据链路控制位于链路层协议&#xff0c;传输单位是帧&#xff0c;它是一组用于在网络结点间传送数据的协议。其特点是各项数据和控制信息都以比特为单位&#xff…

C/C++程序设计实验报告综合作业 | 小小计算器

本文整理自博主本科大一《C/C程序设计》专业课的课内实验报告&#xff0c;适合C语言初学者们学习、练习。 编译器&#xff1a;gcc 10.3.0 ---- 注&#xff1a; 1.虽然课程名为C程序设计&#xff0c;但实际上当时校内该课的内容大部分其实都是C语言&#xff0c;C的元素最多可能只…

2024年第九届数维杯数学建模B题思路分享

文章目录 1 赛题思路2 比赛日期和时间3 竞赛信息4 建模常见问题类型4.1 分类问题4.2 优化问题4.3 预测问题4.4 评价问题 5 建模资料 1 赛题思路 (赛题出来以后第一时间在CSDN分享) https://blog.csdn.net/dc_sinor?typeblog 2 比赛日期和时间 报名截止时间&#xff1a;2024…

六级段落匹配

一个段落最多匹配2个句子 一个段落对应&#xff1a;0-2 适当放题 找到三个对应点就可以选 每看三个句子划关键词之后再自己回忆一遍关键词&#xff0c;看了36 37 38 就复述一遍关键词看了39 40 41就又从36开始复述关键词&#xff08;334&#xff09;看到最后一句话就又从头…

测试平台开发:Django开发实战之注册界面实现(下)

1、 评论和用户建立关联 1&#xff09;修改model: 软关联还是硬关联默认值是什么关联方被删除怎么办如何根据评论找到用户如何根据用户找到评论 然后执行命令&#xff1a; pdm run M pdm run init 这样在表里面就会多一个user_id的字段 2&#xff09;修改视图&#xf…

电脑提示mfc140u.dll文件丢失了?怎么快速修复mfc140u.dll文件

当你的电脑提示你的mfc140u.dll文件丢失了&#xff0c;那么就要小心了&#xff0c;可能你的某些程序出问题了&#xff01;这时候需要我们去进行相关的修复&#xff0c;只有修复了这个mfc140u.dll文件&#xff0c;才能正常的使用某些程序。下面一起来了解一下mfc140u.dll文件吧。…

Deeplab的复现(pytorch实现)

DeepLab复现的pytorch实现 本文复现的主要是deeplabv3。使用的数据集和之前发的文章FCN一样&#xff0c;没有了解的可以移步到之前发的文章中去查看一下。 1.该模型的主要结构 对于代码部分&#xff0c;主要只写了模型部分的&#xff0c;其他部分内容基本和FCN的一致&#xf…

笔试强训Day18 字符串 排序 动态规划

[编程题]压缩字符串(一) 题目链接&#xff1a;压缩字符串(一)__牛客网 (nowcoder.com) 思路&#xff1a; 跟着思路写就完了。 AC code&#xff1a; #include <iostream> #include<string> using namespace std; string a; string ans; int main() {cin >>…

【Java基础】Maven继承

1. 前言 Maven 在设计时&#xff0c;借鉴了 Java 面向对象中的继承思想&#xff0c;提出了 POM 继承思想。 2. Maven继承 当一个项目包含多个模块时&#xff0c;可以在该项目中再创建一个父模块&#xff0c;并在其 POM 中声明依赖&#xff0c;其他模块的 POM 可通过继承父模…

DMAR: [INTR-REMAP] Present field in the IRTE entry is clear 的解决办法

问题描述 在使用FPGA开发PCIe的MSI-X中断相关功能时&#xff0c;一次测试过程中dmesg打印出如下错误&#xff0c;使用cat /proc/interrupts查看FPGA的PCIe驱动程序未收到MSIX中断。使用的系统为基于Intel x86_64的linux&#xff08;RHEL8.9&#xff09;&#xff0c;基于Xilinx …

回归分析的理解

1.是什么&#xff1a; 2.回归问题的求解&#xff1a; 首先是根据之前的数据确定变量和因变量的关系根据关系去预测目标数据根据结果做出判断 2.1如何找到关系&#xff1f; y’是根据模型生成的预测结果&#xff1a; y’axb&#xff0c;而我们的目的是y’和y(正确的结果)之间…

微信小程序相对于H5和原生APP有哪些优势?开发小程序的步骤是什么?

微信小程序是什么&#xff1f; 小程序是小型、轻量级的原生移动应用&#xff0c;你可以使用它们来订餐、预约出租车或支付账单。它们建立在微信平台上&#xff0c;可以通过微信的“小程序”目录进行访问。 与普通应用不同&#xff0c;小程序不需要安装。你可以直接打开并使用…

Ansible --- playbook 脚本+inventory 主机清单

一 inventory 主机清单 Inventory支持对主机进行分组&#xff0c;每个组内可以定义多个主机&#xff0c;每个主机都可以定义在任何一个或 多个主机组内。 如果是名称类似的主机&#xff0c;可以使用列表的方式标识各个主机。vim /etc/ansible/hosts[webservers]192.168.10.1…

js 图片渐变

1. 点击图片&#xff0c;使其渐变为另一张图片 通过定义keyframes来创建一个淡入淡出的动画效果。当图片被点击时&#xff0c;先添加淡出动画使图片透明度从0渐变到1&#xff0c;然后在1秒后切换图片源并添加淡入动画使新图片透明度从0渐变到1&#xff0c;实现图片渐变效果。 …

Hive Views 视图

Hive Views 视图 在Hive中&#xff0c;视图&#xff08;Views&#xff09;是虚拟表&#xff0c;它只包含查询定义&#xff0c;而不包含实际的数据。视图可以简化复杂查询&#xff0c;隐藏数据结构&#xff0c;提供安全性&#xff0c;以及促进数据访问和重用。 创建视图的语法如…

推荐网站(5)Pika文字生成视频,ai视频创作

今天推荐一个网站&#xff0c;Pika文字生成视频&#xff0c;通过问题描述&#xff0c;帮我们生成对应的视频&#xff0c;非常的实用。 比如输入&#xff1a;一只小狗在河边洗澡 当然我们还可以在生成的视频上编辑 点击编辑后出来一些属性&#xff0c;可以修改区域&#xff0c…

MyBatis入门例子

1、建立与数据库对应的POJO类 2、建立mybatis的配置文件 修改后如下&#xff1a; 3、创建POJO对象和Mysql数据的表之间的映射配置 4、建一个测试方法 实现从数据库中取数一条数据&#xff0c;封装成User对象返回 注意点&#xff1a; 这点&#xff0c;大家应该不陌生了&#x…

2024最新行业领域名词解释大全

2024最新行业领域名词解释大全 &#x1f680; 大家好&#xff01;我是你们的老朋友猫头虎&#x1f42f;。今天要为大家带来2024年最新的行业领域名词解释大全&#xff01;在这个信息爆炸的时代&#xff0c;准确了解不同领域的行业动态、工作机会和职业前景至关重要。下面我会分…

Java -- (part22)

一.缓冲流 字节缓冲流 BufferedOutputStream 1.构造 BufferedOutputStream(OutputStream out) 2.用法 和FileOutputStream一样 BufferedInputStream 1.构造 BufferedInputStream(InputStream in) 2.用法 和FileInputStream一样 字符缓冲流 BufferedWriter 1.构造…