Kendo Grid多值字段过滤器添加与移除异常问题排查
解决Kendo Grid多选过滤器重复叠加的问题
我完全懂你遇到的麻烦——每次用弹窗里的MultiSelect设置过滤条件,点击应用后,就算移除了多选里的选项,旧的过滤器还会留在OData查询里,导致条件重复叠加,查询结果越来越窄甚至出错。这都是因为你当前的代码是直接把新生成的过滤器组追加到已有过滤器里,而不是替换掉对应字段的旧过滤器。
问题根源分析
你现在的逻辑是:每次点击应用,先拿到Grid数据源里已有的allFilters,然后把新生成的包含四个多选字段的filter组push进去。这就导致每次操作都会给查询新增一组条件,比如Controller的过滤器,第一次加了(Controller eq 'a' OR Controller eq 'b'),第二次又加(Controller eq 'b'),最终查询就变成了... and (Controller eq 'a' OR Controller eq 'b') and (Controller eq 'b'),完全不符合预期。
解决方案:先清理旧过滤器,再添加新条件
我们需要先从已有过滤器中移除和四个多选字段对应的旧过滤组,再添加新生成的过滤条件,这样就能保证每次应用的都是最新的多选状态。
修改后的代码如下:
// 应用按钮点击事件处理 function applyFilters(gridid) { var filter = { logic: "AND", filters: [] }; var controllerValue = $("#controller").data("kendoMultiSelect").dataItems(); var reconciledByValue = $("#reconciledBy").data("kendoMultiSelect").dataItems(); var reviewedByValue = $("#reviewedBy").data("kendoMultiSelect").dataItems(); var approvedByValue = $("#approvedBy").data("kendoMultiSelect").dataItems(); // 生成新的多选过滤组 if (controllerValue.length > 0) { filter.filters.push(createFilterGroup(controllerValue, "OR", "Controller")); } if (reconciledByValue.length > 0) { filter.filters.push(createFilterGroup(reconciledByValue, "OR", "ReconciledByA")); } if (reviewedByValue.length > 0) { filter.filters.push(createFilterGroup(reviewedByValue, "OR", "ReviewedByA")); } if (approvedByValue.length > 0) { filter.filters.push(createFilterGroup(approvedByValue, "OR", "ApprovedByA")); } var gridDatasource = $("#" + gridid).data("kendoGrid").dataSource; var existingFilters = gridDatasource.filter() || { logic: "AND", filters: [] }; // 定义我们需要管理的字段列表 var managedFields = ["Controller", "ReconciledByA", "ReviewedByA", "ApprovedByA"]; // 过滤掉已有过滤器中属于管理字段的旧过滤组 var updatedFilters = existingFilters.filters.filter(function(existingFilter) { // 判断当前过滤组是否是我们生成的多选字段组:检查组内第一个filter的field是否在管理列表中 if (existingFilter.filters && existingFilter.filters.length > 0) { var field = existingFilter.filters[0].field; return !managedFields.includes(field); } // 如果不是组(单个filter),也检查是否是管理字段(不过你的场景里应该都是组) return !managedFields.includes(existingFilter.field); }); // 把新生成的多选过滤组添加到更新后的过滤器数组中 if (filter.filters.length > 0) { updatedFilters = updatedFilters.concat(filter.filters); } // 设置最终的过滤器 if (updatedFilters.length > 0) { gridDatasource.filter({ logic: existingFilters.logic, filters: updatedFilters }); } else { // 如果没有过滤器了,清空Grid的过滤 gridDatasource.filter({}); } } // 原有的createFilterGroup函数保持不变 function createFilterGroup(filterData, operator, field) { var filterGroup = { logic: operator, filters: [] }; $.each(filterData, function (key, value) { filterGroup.filters.push({ field: field, operator: "eq", value: value[field] }); }); return filterGroup; }
关键逻辑说明
- 清理旧过滤器:通过
managedFields定义我们需要控制的四个字段,然后遍历已有过滤器,移除所有属于这些字段的过滤组(因为我们的多选过滤都是以OR组的形式存在的)。 - 合并新过滤器:把最新生成的多选过滤组添加到清理后的过滤器数组中,而不是追加到旧数组里。
- 空过滤处理:如果所有多选都清空了,就清空Grid的过滤条件,避免残留旧条件。
这样修改后,每次点击应用按钮时,都会先移除之前的多选相关过滤器,再添加最新的条件,OData查询就不会出现重复叠加的问题了。比如:
- 首次选择两个Controller值,查询会包含
(Controller eq 'denekewj' OR Controller eq 'jabbott') - 移除一个Controller值后,旧的Controller组会被删掉,新的组
(Controller eq 'jabbott')会被添加,查询不会出现重复的Controller条件 - 清空Controller并添加ReconciledBy值后,旧的Controller组会被移除,只保留新的ReconciledBy条件
内容的提问来源于stack exchange,提问作者Santosh Kumar
相关产品推荐
相关产品推荐

