jqxGrid使用addfilter函数自定义派生列过滤器失败求助
jqxGrid 合并列过滤问题
我需要在jqxGrid中合并firstname和lastname列为name列,实现用户对name列过滤时,实际搜索firstname或lastname字段。最终要通过updatebounddata将过滤信息发送到服务器,基于datafields返回对应结果,但需要把过滤器的datafields替换为firstname和lastname。
我编写了示例代码,原本期望将name过滤器替换为firstname和lastname过滤器后,const ex和const ex1的值会不同,但实际没有任何更新效果。
HTML代码
<div id='jqxWidget'> <div id="jqxgrid"></div> </div>
原始JavaScript代码
var data = generatedata(500); var source = { localdata: data, datafields: [ { name: "firstname", type: "string" }, { name: "lastname", type: "string" }, { name: "name", type: "string", map: "firstname, lastname" } ], datatype: "array", beforeLoadComplete: function (records) { const data = new Array(); for (var i = 0; i < records.length; i++) { const current = records[i]; current.name = `${current.firstname} ${current.lastname}`; data.push(current); } return data; }, filter: function (filters, b, c) { updateFilters(); } }; var adapter = new $.jqx.dataAdapter(source); $("#jqxgrid").jqxGrid({ width: "100%", theme: "energyblue", source: adapter, filterable: true, showfilterrow: true, columns: [ { text: "Name", datafield: "name", columngroup: "Name", width: 1190 } ] }); function updateFilters() { // Take snapshot of active filters debugger; const ex = $("#jqxgrid").jqxGrid("getfilterinformation"); if (ex.length > 1) { $("#jqxgrid").jqxGrid("updatebounddata"); } else { const activeFilters = []; $.each( $("#jqxgrid").jqxGrid("getfilterinformation"), (index, filterInfo) => { if (filterInfo.datafield === "name") { let value = filterInfo.filter.filtervalue ? filterInfo.filter.filtervalue : filterInfo.filter.getfilters()[0].value; let condition = filterInfo.filter.filtervalue ? filterInfo.filter.comparisonoperator : filterInfo.filter.getfilters()[0].condition; activeFilters.push({ columnName: "firstname", filterValue: value.toLowerCase(), filterCondition: condition.toLowerCase() }); activeFilters.push({ columnName: "lastname", filterValue: value.toLowerCase(), filterCondition: condition.toLowerCase() }); } } ); //$("#jqxgrid").jqxGrid("clearfilters"); // $("#jqxgrid").jqxGrid("removefilter", 'name'); // Update bound data / reset init row etc // Reapply filters activeFilters.forEach((filter) => { const filtergroup = new $.jqx.filter(); filtergroup.operator = "or"; const filtervalue = filter.filterValue; const filtercondition = filter.filterCondition; const filter1 = filtergroup.createfilter( "stringfilter", filtervalue, filtercondition ); filtergroup.addfilter(1, filter1); $("#jqxgrid").jqxGrid("addfilter", filter.columnName, filtergroup); }); const ex1 = $("#jqxgrid").jqxGrid("getfilterinformation"); $("#jqxgrid").jqxGrid("updatebounddata"); //$("#jqxgrid").jqxGrid("refreshfilterrow"); } }
问题分析与修正方案
核心问题
- 未清除原过滤器:代码注释掉了清除
name列过滤器的逻辑,导致原过滤器依然存在,新添加的firstname/lastname过滤器无法替换它,getfilterinformation返回的结果自然不会变化。 - 循环触发事件:在
source.filter事件中调用updateFilters,而updatebounddata又会再次触发filter事件,形成无限循环。 - 过滤器逻辑冗余:单个列的过滤器不需要设置
or操作符,应该将firstname和lastname的过滤器合并为一个or组,或者直接添加两个过滤器后确保逻辑正确。
修正后的JavaScript代码
var data = generatedata(500); var source = { localdata: data, datafields: [ { name: "firstname", type: "string" }, { name: "lastname", type: "string" }, { name: "name", type: "string", map: "firstname, lastname", // 自定义过滤逻辑,直接处理name列的过滤请求 filter: function(value, row) { const searchVal = value.toLowerCase(); return row.firstname.toLowerCase().includes(searchVal) || row.lastname.toLowerCase().includes(searchVal); } } ], datatype: "array", beforeLoadComplete: function (records) { return records.map(current => ({ ...current, name: `${current.firstname} ${current.lastname}` })); } }; var adapter = new $.jqx.dataAdapter(source); $("#jqxgrid").jqxGrid({ width: "100%", theme: "energyblue", source: adapter, filterable: true, showfilterrow: true, columns: [ { text: "Name", datafield: "name", columngroup: "Name", width: 1190 } ], // 改用filterrow事件处理,避免循环调用 filterrow: function() { $("#jqxgrid").jqxGrid("updatebounddata"); } });
关键改动说明
- 自定义列过滤逻辑:在
name列的datafields中添加filter函数,直接判断firstname或lastname是否包含搜索值,无需替换过滤器的datafields,更简洁高效。 - 简化数据处理:用
map替代原循环构建数据,代码更简洁。 - 替换事件触发时机:改用
filterrow事件触发数据更新,避免filter事件的循环调用问题。
如果需要将过滤参数发送到服务器,可以在source.beforeSend事件中修改请求参数,将name的过滤条件转换为firstname和lastname的OR条件:
var source = { // ... 其他配置 beforeSend: function(xhr, settings) { // 获取当前过滤器信息 const filterInfo = $("#jqxgrid").jqxGrid("getfilterinformation"); if (filterInfo.length > 0 && filterInfo[0].datafield === "name") { const filter = filterInfo[0].filter; const value = filter.filtervalue || filter.getfilters()[0].value; const condition = filter.comparisonoperator || filter.getfilters()[0].condition; // 构建服务器需要的过滤参数,替换name为firstname和lastname的OR条件 const newFilter = { groupoperator: "or", filters: [ { datafield: "firstname", condition, value }, { datafield: "lastname", condition, value } ] }; // 修改请求数据,这里根据实际请求格式调整 const data = JSON.parse(settings.data); data.filter = newFilter; settings.data = JSON.stringify(data); } } };
内容的提问来源于stack exchange,提问作者heyNow
相关产品推荐
相关产品推荐

