vue3+arco design通過(guò)動(dòng)態(tài)表單方式實(shí)現(xiàn)自定義篩選功能
1.說(shuō)明
(1) 本文主要實(shí)現(xiàn)通過(guò)動(dòng)態(tài)表單的方式實(shí)現(xiàn)自定義篩選的功能,用戶可以自己添加篩選的項(xiàng)目,篩選條件及篩選內(nèi)容。
(2) 每個(gè)項(xiàng)目的篩選包含篩選項(xiàng)目,篩選條件,篩選方式及篩選值。
篩選項(xiàng)目代表表中的字段,如姓名,年齡等
篩選條件包含等于,不等于,大于,小于,包含等
篩選類型包含手動(dòng)輸入值的方式,通過(guò)下拉進(jìn)行選擇的方式,和表中的其他字段進(jìn)行比較的方式
篩選值可以手動(dòng)輸入,可以通過(guò)下拉進(jìn)行選擇,也可以選擇某個(gè)日期。
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("校驗(yàn)失敗")
}
}
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不支持和其他列進(jìn)行比較', 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] = []
}
}
}
}
// 打開(kāi)彈窗
const openDialog = () => {
visibleFlag.value = true;
};
// 導(dǎo)出方法在父組件中進(jìn)行使用
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'
}
]
}
// 組件完成初始渲染并創(chuàng)建 DOM 節(jié)點(diǎn)后運(yùn)行
onMounted(async () => {
await getColumnList()
})
</script>
<script lang="ts">
export default {
name: "dynamicFilter"
}
</script>
<style scoped>
</style>說(shuō)明:
①通過(guò)表單的方式進(jìn)行實(shí)現(xiàn),表單關(guān)聯(lián)的數(shù)據(jù)源form是對(duì)象格式,如下:
const form = ref({
data: [{
filterColumn: '',
filterOperation: '',
filterType: '',
filterValue: ''
}]
})對(duì)象內(nèi)是一個(gè)id為data的數(shù)組,數(shù)組內(nèi)的每條數(shù)組則存儲(chǔ)一個(gè)項(xiàng)目的篩選內(nèi)容,包含篩選項(xiàng)目,篩選條件,篩選方式及篩選值。數(shù)據(jù)源設(shè)置為對(duì)象是為了進(jìn)行校驗(yàn)處理,如果是數(shù)組格式,無(wú)法實(shí)現(xiàn)動(dòng)態(tài)表單的的校驗(yàn)(不同的前端框架,可能會(huì)有所不同,但推薦使用對(duì)象格式)
②動(dòng)態(tài)表單的實(shí)現(xiàn)
在form標(biāo)簽內(nèi)嵌套div標(biāo)簽,并在div標(biāo)簽上進(jìn)行循環(huán)form.data,如果動(dòng)態(tài)的項(xiàng)目只有一個(gè),可以直接在form-item上進(jìn)行循環(huán)處理。具體的每個(gè)表單項(xiàng)可以通過(guò)form.data[index].表單項(xiàng)名的方式進(jìn)行綁定,也可以通過(guò)item.表單項(xiàng)名的方式進(jìn)行綁定。點(diǎn)擊新增按鈕,會(huì)向form.data中push一條新數(shù)據(jù),添加的篩選項(xiàng)目后面有刪除按鈕,點(diǎn)擊刪除按鈕,通過(guò)form.data.splice方法刪除數(shù)組中的元素。
③動(dòng)態(tài)表單的校驗(yàn)處理
在每個(gè)表單項(xiàng)中添加校驗(yàn)規(guī)則,不要在form上添加校驗(yàn)規(guī)則
在arco design框架中的動(dòng)態(tài)表單校驗(yàn)如下:
<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>通過(guò)rules關(guān)聯(lián)校驗(yàn)規(guī)則,注意field屬性的設(shè)置,在arco design中field需要進(jìn)行如上設(shè)置,結(jié)果例如:data[0].filterColumn。
在arco design中是設(shè)置field屬性,在element ui中是設(shè)置prop屬性,并且內(nèi)容的設(shè)置方式也不一樣,需要注意。
④提交時(shí)的校驗(yàn)
當(dāng)前表單嵌套在對(duì)話框中,點(diǎn)擊確定按鈕時(shí),需要先進(jìn)行表單的校驗(yàn)處理,如下:
const handleOk = async () => {
const validRes = await formRef.value?.validate();
if (!validRes) {
visibleFlag.value = false;
console.log(JSON.stringify(form.value.data))
} else {
console.log("校驗(yàn)失敗")
}
}通過(guò)調(diào)用表單的ref對(duì)象的validate方法,如果校驗(yàn)失敗則返回失敗的項(xiàng)目的field屬性內(nèi)容及錯(cuò)誤信息,如果成功則返回undefined,所以通過(guò)判斷返回結(jié)果就可以判斷校驗(yàn)成功與否。
校驗(yàn)失敗的返回信息如下
{
"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不能為空"
}
}校驗(yàn)通過(guò)后輸出的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.運(yùn)行截圖
校驗(yàn)失敗

輸入內(nèi)容后,校驗(yàn)通過(guò)

4.總結(jié)
①注意表單綁定的數(shù)據(jù)源的格式及不同前端框架的校驗(yàn)的方式
②為了使畫(huà)面更加友好,可以將表單放在表格中
到此這篇關(guān)于vue3+arco design通過(guò)動(dòng)態(tài)表單方式實(shí)現(xiàn)自定義篩選的文章就介紹到這了,更多相關(guān)vue3自定義篩選內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Vue如何實(shí)現(xiàn)多頁(yè)面配置以及打包方式
這篇文章主要介紹了Vue如何實(shí)現(xiàn)多頁(yè)面配置以及打包方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-10-10
vuejs如何解決瀏覽器切換頁(yè)面后setInterval計(jì)時(shí)器停止執(zhí)行的問(wèn)題
setinterval()是定時(shí)調(diào)用的函數(shù),可按照指定的周期(以毫秒計(jì))來(lái)調(diào)用函數(shù)或計(jì)算表達(dá)式,這篇文章主要給大家介紹了關(guān)于vuejs如何解決瀏覽器切換頁(yè)面后setInterval計(jì)時(shí)器停止執(zhí)行的問(wèn)題,需要的朋友可以參考下2024-01-01
vue項(xiàng)目實(shí)現(xiàn)登陸注冊(cè)效果
這篇文章主要為大家詳細(xì)介紹了vue項(xiàng)目實(shí)現(xiàn)登陸注冊(cè)效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09
vue中json格式化顯示數(shù)據(jù)(vue-json-viewer)
這篇文章主要給大家介紹了關(guān)于vue中json格式化顯示數(shù)據(jù)(vue-json-viewer)的相關(guān)資料,Vue-json-viewer是一個(gè)Vue組件,用于在Vue應(yīng)用中顯示JSON數(shù)據(jù)的可視化工具,需要的朋友可以參考下2024-05-05

