赞
踩
官网例子:https://vxetable.cn/#/table/renderer/filter
进入之后:我们可以参照例子自行实现,也可以下载它的源码,进行调整
下载好后并解压,用vscode将解压后的文件打开。全局检索FilterInput,你工作中用的vxe-table多少版本的那就进多少版本的目录
点击进入,按照这个路劲找到对应文件夹
将filter相关的vue,复制到自己的项目中components文件夹下
将filter.tsx 到你的项目中去,常用的FilterInput和FilterContent组件,将其他的FilterExtend 和FilterComplex 相关的可以先注释掉。
打开filter.ts
这样就可以使用了,使用方式,按照官网的例子放到columns里即可,filters的结构不允许改变,他与filterRendes的组件是一一对应的
这里提供v4的相关源码代码:
FilterInput.vue
<template> <div class="my-filter-input"> <vxe-input type="text" v-model="demo1.option.data" placeholder="支持回车筛选" @keyup="keyupEvent" @input="changeOptionEvent"></vxe-input> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue' import { VxeInputEvents, VxeGlobalRendererHandles } from 'vxe-table' export default defineComponent({ name: 'FilterInput', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams> }, setup (props) { const demo1 = reactive({ option: null as any }) const load = () => { const { params } = props if (params) { const { column } = params const option = column.filters[0] demo1.option = option } } const changeOptionEvent = () => { const { params } = props const { option } = demo1 if (params && option) { const { $panel } = params const checked = !!option.data $panel.changeOption(null, checked, option) } } const keyupEvent: VxeInputEvents.Keyup = ({ $event }) => { const { params } = props if (params) { const { $panel } = params if ($event.keyCode === 13) { $panel.confirmFilter($event) } } } load() return { demo1, changeOptionEvent, keyupEvent } } }) </script> <style scoped> .my-filter-input { padding: 10px; } </style>
FilterContent.vue
<template> <div class="my-filter-content"> <div class="my-fc-search"> <div class="my-fc-search-top"> <vxe-input v-model="demo1.option.data.sVal" placeholder="搜索"></vxe-input> </div> <div class="my-fc-search-content"> <template v-if="demo1.valList.length"> <ul class="my-fc-search-list my-fc-search-list-head"> <li class="my-fc-search-item"> <vxe-checkbox v-model="demo1.isAll" @change="changeAllEvent">全选</vxe-checkbox> </li> </ul> <ul class="my-fc-search-list my-fc-search-list-body"> <li class="my-fc-search-item" v-for="(item, sIndex) in demo1.valList" :key="sIndex"> <vxe-checkbox v-model="item.checked">{{ item.value }}</vxe-checkbox> </li> </ul> </template> <template v-else> <div class="my-fc-search-empty">无匹配项</div> </template> </div> </div> <div class="my-fc-footer"> <vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button> <vxe-button @click="resetFilterEvent">重置</vxe-button> </div> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue' import { VxeGlobalRendererHandles } from 'vxe-table' import XEUtils from 'xe-utils' export default defineComponent({ name: 'FilterContent', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams> }, setup (props) { interface ColValItem { checked: boolean; value: string; } const demo1 = reactive({ isAll: false, option: null as any, colValList: [] as ColValItem[], valList: [] as ColValItem[] }) const load = () => { const { params } = props if (params) { const { $table, column } = params const { fullData } = $table.getTableData() const option = column.filters[0] const { vals } = option.data const colValList = Object.keys(XEUtils.groupBy(fullData, column.field)).map((val) => { return { checked: vals.includes(val), value: val } as ColValItem }) demo1.option = option demo1.colValList = colValList demo1.valList = colValList } } const searchEvent = () => { const { option, colValList } = demo1 if (option) { demo1.valList = option.data.sVal ? colValList.filter((item) => item.value.indexOf(option.data.sVal) > -1) : colValList } } const changeAllEvent = () => { const { isAll } = demo1 demo1.valList.forEach((item) => { item.checked = isAll }) } const confirmFilterEvent = () => { const { params } = props const { option, valList } = demo1 if (params && option) { const { data } = option const { $panel } = params data.vals = valList.filter((item) => item.checked).map((item) => item.value) $panel.changeOption(null, true, option) $panel.confirmFilter() } } const resetFilterEvent = () => { const { params } = props if (params) { const { $panel } = params $panel.resetFilter() } } load() return { demo1, searchEvent, changeAllEvent, confirmFilterEvent, resetFilterEvent } } }) </script> <style> .my-filter-content { padding: 10px; user-select: none; } .my-filter-content .my-fc-search .my-fc-search-top { position: relative; padding: 5px 0; } .my-filter-content .my-fc-search .my-fc-search-top > input { border: 1px solid #ABABAB; padding: 0 20px 0 2px; width: 200px; height: 22px; line-height: 22px; } .my-filter-content .my-fc-search .my-fc-search-content { padding: 2px 10px; } .my-filter-content .my-fc-search-empty { text-align: center; padding: 20px 0; } .my-filter-content .my-fc-search-list { margin: 0; padding: 0; list-style: none; } .my-filter-content .my-fc-search-list-body { overflow: auto; height: 120px; } .my-filter-content .my-fc-search-list .my-fc-search-item { padding: 2px 0; display: block; } .my-filter-content .my-fc-footer { text-align: right; padding-top: 10px; } .my-filter-content .my-fc-footer button { padding: 0 15px; margin-left: 15px; } </style>
FilterExtend.vue
<template> <div class="my-filter-excel"> <div class="my-fe-top"> <ul class="my-fe-menu-group"> <li class="my-fe-menu-link"> <span>升序</span> </li> <li class="my-fe-menu-link"> <span>倒序</span> </li> </ul> <ul class="my-fe-menu-group"> <li class="my-fe-menu-link" @click="resetFilterEvent"> <span>清除筛选</span> </li> <li class="my-fe-menu-link"> <i class="vxe-icon-question-circle-fill my-fe-menu-link-left-icon"></i> <span>筛选条件</span> <i class="vxe-icon-question-circle-fill my-fe-menu-link-right-icon"></i> <div class="my-fe-menu-child-list"> <ul class="my-fe-child-menu-group-list" v-for="(cList, gIndex) in demo1.caseGroups" :key="gIndex"> <li v-for="(cItem, cIndex) in cList" :key="cIndex" class="my-fe-child-menu-item" @click="childMenuClickEvent(cItem)"> <span>{{ cItem.label }}</span> </li> </ul> </div> </li> </ul> </div> <div class="my-fe-search"> <div class="my-fe-search-top"> <input v-model="demo1.option.data.sVal" placeholder="搜索"/> <i class="vxe-icon-question-circle-fill my-fe-search-icon"></i> </div> <ul class="my-fe-search-list"> <li class="my-fe-search-item" @click="sAllEvent"> <i class="vxe-icon-question-circle-fill my-fe-search-item-icon"></i> <span>(全选)</span> </li> <li class="my-fe-search-item" v-for="(val, sIndex) in searchList" :key="sIndex" @click="sItemEvent(val)"> <i :class="[demo1.option.data.vals.indexOf(val) === -1 ? 'vxe-icon-question-circle-fill my-fe-search-item-icon' : 'vxe-icon-question-circle-fill my-fe-search-item-icon']"></i> <span>{{ val }}</span> </li> </ul> </div> <div class="my-fe-footer"> <vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button> <vxe-button @click="resetFilterEvent">重置</vxe-button> </div> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive, computed } from 'vue' import { VXETable, VxeGlobalRendererHandles } from 'vxe-table' import XEUtils from 'xe-utils' export default defineComponent({ name: 'FilterExtend', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams> }, setup (props) { interface CaseItem { label: string; value: string; } const demo1 = reactive({ option: null as any, colValList: [] as string[], caseGroups: [ [ { value: 'equal', label: '等于' }, { value: 'ne', label: '不等于' } ], [ { value: 'greater', label: '大于' }, { value: 'ge', label: '大于或等于' }, { value: 'less', label: '小于' }, { value: 'le', label: '小于或等于' } ] ] as CaseItem[][] }) const searchList = computed(() => { const { option, colValList } = demo1 if (option) { return option.data.sVal ? colValList.filter(val => val.indexOf(option.data.sVal) > -1) : colValList } return [] }) const load = () => { const { params } = props if (params) { const { $table, column } = params const { fullData } = $table.getTableData() const option = column.filters[0] const colValList = Object.keys(XEUtils.groupBy(fullData, column.field)) demo1.option = option demo1.colValList = colValList } } const sAllEvent = () => { const { option } = demo1 if (option) { const { data } = option if (data.vals.length > 0) { data.vals = [] } else { data.vals = demo1.colValList } } } const sItemEvent = (val: string) => { const { option } = demo1 if (option) { const { data } = option const vIndex = data.vals.indexOf(val) if (vIndex === -1) { data.vals.push(val) } else { data.vals.splice(vIndex, 1) } } } const confirmFilterEvent = () => { const { params } = props const { option } = demo1 if (params && option) { const { data } = option const { $panel } = params data.f1 = '' data.f2 = '' $panel.changeOption(null, true, option) $panel.confirmFilter() } } const resetFilterEvent = () => { const { params } = props if (params) { const { $panel } = params $panel.resetFilter() } } const childMenuClickEvent = (cItem: CaseItem) => { VXETable.modal.alert({ content: cItem.label }) } load() return { demo1, searchList, sAllEvent, sItemEvent, confirmFilterEvent, resetFilterEvent, childMenuClickEvent } } }) </script> <style> .my-filter-excel { user-select: none; } .my-filter-excel .my-fe-top .my-fe-menu-group { position: relative; margin: 0; padding: 0; } .my-filter-excel .my-fe-top .my-fe-menu-group:after { content: ""; position: absolute; width: 190px; right: 0; bottom: 0; border-bottom: 1px solid #E2E4E7; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link { position: relative; padding: 4px 20px 4px 30px; cursor: pointer; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link:hover { background-color: #C5C5C5; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link-left-icon { position: absolute; left: 10px; top: 6px; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link-right-icon { position: absolute; right: 10px; top: 6px; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link:hover .my-fe-menu-child-list { display: block; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-menu-child-list { display: none; position: absolute; top: 0; right: -120px; width: 120px; background-color: #fff; border: 1px solid #DADCE0; box-shadow: 3px 3px 4px -2px rgba(0, 0, 0, 0.6); } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list { position: relative; padding: 0; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list:after { content: ""; position: absolute; width: 90px; right: 0; bottom: 0; border-bottom: 1px solid #E2E4E7; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list > .my-fe-child-menu-item { position: relative; padding: 4px 20px 4px 30px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; } .my-filter-excel .my-fe-top .my-fe-menu-group .my-fe-menu-link .my-fe-child-menu-group-list > .my-fe-child-menu-item:hover { background-color: #C5C5C5; } .my-filter-excel .my-fe-search { padding: 0 10px 0 30px; } .my-filter-excel .my-fe-search .my-fe-search-top { position: relative; padding: 5px 0; } .my-filter-excel .my-fe-search .my-fe-search-top > input { border: 1px solid #ABABAB; padding: 0 20px 0 2px; width: 200px; height: 22px; line-height: 22px; } .my-filter-excel .my-fe-search .my-fe-search-top > .my-fe-search-icon { position: absolute; right: 5px; top: 10px; } .my-filter-excel .my-fe-search .my-fe-search-list { margin: 0; border: 1px solid #E2E4E7; padding: 2px 10px; overflow: auto; height: 140px; } .my-filter-excel .my-fe-search .my-fe-search-list .my-fe-search-item { cursor: pointer; padding: 2px 0; } .my-filter-excel .my-fe-search .my-fe-search-list .my-fe-search-item .my-fe-search-item-icon { width: 16px; } .my-filter-excel .my-fe-footer { text-align: right; padding: 10px 10px 10px 0; } .my-fe-popup .my-fe-popup-filter { padding-left: 30px; } .my-fe-popup .my-fe-popup-filter > .my-fe-popup-filter-select { width: 120px; } .my-fe-popup .my-fe-popup-filter > .my-fe-popup-filter-input { margin-left: 15px; width: 380px; } .my-fe-popup .my-fe-popup-describe { padding: 20px 0 10px 0; } .my-fe-popup .my-fe-popup-concat { padding-left: 50px; } .my-fe-popup .my-fe-popup-footer { text-align: right; } </style>
FilterComplex.vue
<template> <div class="my-filter-complex"> <div class="my-fc-type"> <vxe-radio v-model="demo1.option.data.type" name="fType" label="has">包含</vxe-radio> <vxe-radio v-model="demo1.option.data.type" name="fType" label="eq">等于</vxe-radio> </div> <div class="my-fc-name"> <vxe-input v-model="demo1.option.data.name" type="text" placeholder="请输入名称" @input="changeOptionEvent()"></vxe-input> </div> <div class="my-fc-footer"> <vxe-button status="primary" @click="confirmEvent">确认</vxe-button> <vxe-button @click="resetEvent">重置</vxe-button> </div> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue' import { VxeGlobalRendererHandles } from 'vxe-table' export default defineComponent({ name: 'FilterComplex', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams> }, setup (props) { const demo1 = reactive({ option: null as any }) const load = () => { const { params } = props if (params) { const { column } = params const option = column.filters[0] demo1.option = option } } const changeOptionEvent = () => { const { params } = props const { option } = demo1 if (params && option) { const { $panel } = params const checked = !!option.data.name $panel.changeOption(null, checked, option) } } const confirmEvent = () => { const { params } = props if (params) { const { $panel } = params $panel.confirmFilter() } } const resetEvent = () => { const { params } = props if (params) { const { $panel } = params $panel.resetFilter() } } load() return { demo1, changeOptionEvent, confirmEvent, resetEvent } } }) </script> <style scoped> .my-filter-complex { width: 260px; padding: 5px 15px 10px 15px; } .my-filter-complex .my-fc-type { padding: 8px 0; } .my-filter-complex .my-fc-footer { text-align: center; } </style>
filter.tsx
import { VXETable } from 'vxe-table' import FilterInput from './components/FilterInput.vue' import FilterContent from './components/FilterContent.vue' import FilterComplex from './components/FilterComplex.vue' import FilterExtend from './components/FilterExtend.vue' // 创建一个简单的输入框筛选 VXETable.renderer.add('FilterInput', { // 筛选模板 renderFilter (renderOpts, params) { return <FilterInput params={ params }></FilterInput> }, // 重置数据方法 filterResetMethod (params) { const { options } = params options.forEach((option) => { option.data = '' }) }, // 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值) filterRecoverMethod ({ option }) { option.data = '' }, // 筛选方法 filterMethod (params) { const { option, row, column } = params const { data } = option const cellValue = row[column.field] if (cellValue) { return cellValue.indexOf(data) > -1 } return false } }) // 创建一个条件的渲染器 VXETable.renderer.add('FilterComplex', { // 不显示底部按钮,使用自定义的按钮 showFilterFooter: false, // 筛选模板 renderFilter (renderOpts, params) { return <FilterComplex params={ params }></FilterComplex> }, // 重置数据方法 filterResetMethod (params) { const { options } = params options.forEach((option) => { option.data = { type: 'has', name: '' } }) }, // 筛选数据方法 filterMethod (params) { const { option, row, column } = params const cellValue = row[column.field] const { name } = option.data if (cellValue) { return cellValue.indexOf(name) > -1 } return false } }) // 创建一个支持列内容的筛选 VXETable.renderer.add('FilterContent', { // 不显示底部按钮,使用自定义的按钮 showFilterFooter: false, // 筛选模板 renderFilter (renderOpts, params) { return <FilterContent params={ params }></FilterContent> }, // 重置数据方法 filterResetMethod (params) { const { options } = params options.forEach((option) => { option.data = { vals: [], sVal: '' } }) }, // 筛选数据方法 filterMethod (params) { const { option, row, column } = params const { vals } = option.data const cellValue = row[column.field] return vals.includes(cellValue) } }) // 创建一个复杂的筛选器 VXETable.renderer.add('FilterExtend', { // 不显示底部按钮,使用自定义的按钮 showFilterFooter: false, // 筛选模板 renderFilter (renderOpts, params) { return <FilterExtend params={ params }></FilterExtend> }, // 重置数据方法 filterResetMethod (params) { const { options } = params options.forEach((option) => { option.data = { vals: [], sVal: '', fMenu: '', f1Type: '', f1Val: '', fMode: 'and', f2Type: '', f2Val: '' } }) }, // 筛选数据方法 filterMethod (params) { const { option, row, column } = params const cellValue = row[column.field] const { vals, f1Type, f1Val } = option.data if (cellValue) { if (f1Type) { return cellValue.indexOf(f1Val) > -1 } else if (vals.length) { // 通过指定值筛选 return vals.includes(cellValue) } } return false } })
通过上面的方式,已经实现了过滤器,但是多次使用,衍生出一个问题,就是如果我的列是个字典列,并且字典值的转换用的是columns内的solt,如FilterContent组件,它将会渲染的时字典的value列表,并非用户看到的中文列表,用户怎么知道你过滤器的看到的1,2,3和你的数据时对应的,或者时FilterInput 你输入的必须时字典code,不能是中文,否则将无法筛选出数据。
解决问题1: 在数据库查询数据时,根据该列关联字典表,将中文给转换过来,
解决问题2:前端查询数据后,在给表格赋值时将字典数据转换回来,这样有些麻烦,
解决问题3:优化筛选组件,使其支持字典的筛选。由于项目中只用到了FilterInput和FilterContent这里只提供这两个组件的优化。
1. 先说下在哪里做了调整
filtes的结构上做了些调整,data里都增加了字典的数据, filterContent 参数移除sval参数,同样在filterContent 组件内input筛选也将被移除,只保留多选列表进行筛选
FilterInput
“FilterContent.vue”,它与FilterInput不一样,需要面板打开时,就显示过滤列表
2. 调整后的代码
FilterContent.vue
<template> <div class="my-filter-content"> <div class="my-fc-search"> <div class="my-fc-search-top"> <!-- <vxe-input v-model="demo1.option.data.sVal" placeholder="搜索" ></vxe-input> --> </div> <div class="my-fc-search-content"> <template v-if="demo1.valList.length"> <ul class="my-fc-search-list my-fc-search-list-head"> <li class="my-fc-search-item"> <vxe-checkbox v-model="demo1.isAll" @change="changeAllEvent" >全选</vxe-checkbox > </li> </ul> <ul class="my-fc-search-list my-fc-search-list-body"> <li v-for="(item, sIndex) in demo1.valList" :key="sIndex" class="my-fc-search-item" > <vxe-checkbox v-model="item.checked">{{ item.label }}</vxe-checkbox> </li> </ul> </template> <template v-else> <div class="my-fc-search-empty">无匹配项</div> </template> </div> </div> <div class="my-fc-footer"> <vxe-button status="primary" @click="confirmFilterEvent">确认</vxe-button> <vxe-button @click="resetFilterEvent">重置</vxe-button> </div> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue'; import { VxeGlobalRendererHandles } from 'vxe-table'; import XEUtils from 'xe-utils'; export default defineComponent({ name: 'FilterContent', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>, }, setup(props) { interface ColValItem { checked: boolean; value: string; label: string; } const demo1 = reactive({ isAll: false, option: null as any, colValList: [] as ColValItem[], valList: [] as ColValItem[], }); const load = () => { const { params } = props; if (params) { const { $table, column } = params; const { fullData } = $table.getTableData(); const option: any = column.filters[0]; const { vals } = option.data; /* * 重置数据,解决bug:可能由于动态渲染columns,导致过滤面板勾选后点击确认按钮,过滤后无法更新表格数据, * 经过尝试,点击重置按钮,在进行过滤,可正常过滤,所以这里重置下data ;问题得以解决 */ option.data = { vals: option.data.vals, // sVal: option.data.sVal, dict: option.data.dict ? option.data.dict : undefined, }; if (option.data.dict && option.data.dict.length > 0) { const colValList = Object.keys( XEUtils.groupBy(fullData, column.field) ).map((val) => { const value = option.data.dict.filter( (item) => String(item.value) === String(val) ); let label = val; if (value.length > 0) { label = value[0] .label; } return { checked: vals.includes(val), value: val, label, } as ColValItem; }); demo1.option = option; demo1.colValList = colValList; demo1.valList = colValList; } else { const colValList = Object.keys( XEUtils.groupBy(fullData, column.field) ).map((val) => { return { checked: vals.includes(val), value: val, label: val, } as ColValItem; }); demo1.option = option; demo1.colValList = colValList; demo1.valList = colValList; } } }; // const searchEvent = () => { // const { option, colValList } = demo1; // if (option) { // demo1.valList = option.data.sVal // ? colValList.filter( // (item) => item.value.indexOf(option.data.sVal) > -1 // ) // : colValList; // } // }; const changeAllEvent = () => { const { isAll } = demo1; demo1.valList.forEach((item) => { item.checked = isAll; }); }; const confirmFilterEvent = () => { const { params } = props; const { option, valList } = demo1; if (params && option) { const { data } = option; const { $panel } = params; data.vals = valList .filter((item) => item.checked) .map((item) => item.value); $panel.changeOption(null, true, option); $panel.confirmFilter(); } }; const resetFilterEvent = () => { const { params } = props; if (params) { const { $panel } = params; $panel.resetFilter(); } }; load(); return { demo1, // searchEvent, changeAllEvent, confirmFilterEvent, resetFilterEvent, }; }, }); </script> <style> .my-filter-content { padding: 10px; user-select: none; } .my-filter-content .my-fc-search .my-fc-search-top { position: relative; padding: 5px 0; } .my-filter-content .my-fc-search .my-fc-search-top > input { border: 1px solid #ababab; padding: 0 20px 0 2px; width: 200px; height: 22px; line-height: 22px; } .my-filter-content .my-fc-search .my-fc-search-content { padding: 2px 10px; } .my-filter-content .my-fc-search-empty { text-align: center; padding: 20px 0; } .my-filter-content .my-fc-search-list { margin: 0; padding: 0; list-style: none; } .my-filter-content .my-fc-search-list-body { overflow: auto; height: 120px; } .my-filter-content .my-fc-search-list .my-fc-search-item { padding: 2px 0; display: block; } .my-filter-content .my-fc-footer { text-align: right; padding-top: 10px; } .my-filter-content .my-fc-footer button { padding: 0 15px; margin-left: 15px; } </style>
FilterInput.vue
<template> <div class="my-filter-input"> <vxe-input v-model="demo1.option.data.sVal" type="text" placeholder="支持回车筛选" @keyup="keyupEvent" @input="changeOptionEvent" ></vxe-input> </div> </template> <script lang="ts"> import { defineComponent, PropType, reactive } from 'vue'; import { VxeInputEvents, VxeGlobalRendererHandles } from 'vxe-table'; export default defineComponent({ name: 'FilterInput', props: { params: Object as PropType<VxeGlobalRendererHandles.RenderFilterParams>, }, setup(props) { const demo1 = reactive({ option: null as any, }); const load = () => { const { params } = props; if (params) { const { column } = params; const option = column.filters[0]; option.data = { sVal: option.data.sVal, dict: option.data.dict ? option.data.dict : undefined, }; demo1.option = option; } }; const changeOptionEvent = () => { const { params } = props; const { option } = demo1; if (params && option) { const { $panel } = params; const checked = !!option.data.sVal; $panel.changeOption(null, checked, option); } }; const keyupEvent: VxeInputEvents.Keyup = ({ $event }) => { const { params } = props; if (params) { const { $panel } = params; if ($event.keyCode === 13) { $panel.confirmFilter($event); } } }; load(); return { demo1, changeOptionEvent, keyupEvent, }; }, }); </script> <style scoped> .my-filter-input { padding: 10px; } </style>
filter.tsx
import { VXETable } from 'vxe-table'; import FilterInput from '@/components/Filter/FilterInput.vue'; import FilterContent from '@/components/Filter/FilterContent.vue'; // import FilterComplex from './components/FilterComplex.vue' // import FilterExtend from './components/FilterExtend.vue' // 创建一个简单的输入框筛选 VXETable.renderer.add('FilterInput', { // 筛选模板 renderFilter: (renderOpts, params) => { return [<FilterInput params={ params }></FilterInput>]; }, // 重置数据方法 filterResetMethod (params) { const { options } = params; options.forEach((option) => { option.data = { sVal: '', dict: option.data.dict ? option.data.dict : undefined, }; }); }, // 重置筛选复原方法(当未点击确认时,该选项将被恢复为默认值) filterRecoverMethod ({ option }) { option.data = { sVal: '', dict: option.data.dict ? option.data.dict : undefined, }; }, // 筛选方法 filterMethod (params) { const { option, row, column } = params; const { data } = option; if(data.dict && data.dict.length > 0) { const cellValue = row[column.field]; const dictItem = data.dict.filter((item)=>item.label.indexOf(data.sVal) > -1).map((item) => item.value); if(dictItem.length > 0){ return dictItem.indexOf(cellValue) > -1; } } else { const cellValue = row[column.field]; if (cellValue) { return cellValue.indexOf(data.sVal) > -1; } } return false; }, }); // // 创建一个条件的渲染器 // VXETable.renderer.add('FilterComplex', { // // 不显示底部按钮,使用自定义的按钮 // showFilterFooter: false, // // 筛选模板 // renderFilter (renderOpts, params) { // return <FilterComplex params={ params }></FilterComplex> // }, // // 重置数据方法 // filterResetMethod (params) { // const { options } = params // options.forEach((option) => { // option.data = { type: 'has', name: '' } // }) // }, // // 筛选数据方法 // filterMethod (params) { // const { option, row, column } = params // const cellValue = row[column.field] // const { name } = option.data // if (cellValue) { // return cellValue.indexOf(name) > -1 // } // return false // } // }) // 创建一个支持列内容的筛选 VXETable.renderer.add('FilterContent', { // 不显示底部按钮,使用自定义的按钮 showFilterFooter: false, // 筛选模板 renderFilter (renderOpts, params) { return [<FilterContent params={ params }></FilterContent>]; }, // 重置数据方法 filterResetMethod (params) { const { options } = params; options.forEach((option) => { option.data = { vals: [],dict: option.data.dict ? option.data.dict : undefined}; }); }, // 筛选数据方法 filterMethod (params) { const { option, row, column } = params; const { vals } = option.data; const cellValue = row[column.field]; console.log(cellValue,vals.includes(cellValue)) return vals.includes(cellValue); }, }); // // 创建一个复杂的筛选器 // VXETable.renderer.add('FilterExtend', { // // 不显示底部按钮,使用自定义的按钮 // showFilterFooter: false, // // 筛选模板 // renderFilter (renderOpts, params) { // return <FilterExtend params={ params }></FilterExtend> // }, // // 重置数据方法 // filterResetMethod (params) { // const { options } = params // options.forEach((option) => { // option.data = { vals: [], sVal: '', fMenu: '', f1Type: '', f1Val: '', fMode: 'and', f2Type: '', f2Val: '' } // }) // }, // // 筛选数据方法 // filterMethod (params) { // const { option, row, column } = params // const cellValue = row[column.field] // const { vals, f1Type, f1Val } = option.data // if (cellValue) { // if (f1Type) { // return cellValue.indexOf(f1Val) > -1 // } else if (vals.length) { // // 通过指定值筛选 // return vals.includes(cellValue) // } // } // return false // } // })
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。