Bootstrap-table自定义联动筛选开发及选中值丢失问题求助
我使用Bootstrap-Table(1.20和1.21.4版本)实现列下拉筛选的联动效果:选中第一个下拉框选项后,另外两个下拉框仅展示与该选择相关的值。尝试过官方的hideUnusedSelectOptions选项,但效果不稳定,因此自行开发了自定义筛选逻辑:
- 监听
column-search.bs.table事件捕获选中的下拉框 - 在
page-change.bs.table事件中填充其他下拉框,此时数据已按第一个筛选条件完成过滤
但目前遇到的问题是:选中选项后的第一个下拉框会变成空白无值状态。怀疑是执行$table.bootstrapTable('filterBy', newFilter)时触发了包括page-change.bs.table在内的一系列事件导致的,相关代码如下:
$table.on('all.bs.table', function (e, name, args) { var event='page-change.bs.table'; var pref = '.bootstrap-table-filter-control-'; if (name == event && DataLoadedInTable == true && filterApplied == true) { switch (filterField) { case 'DEPARTMENT': case 'UO_DESC': case 'LEVPROF': var data = $("#table").bootstrapTable('getData', { unfiltered: false, includeHiddenRows:false}); break; default: return false; break; } FilterApplied1Time = true; if (filterField != 'DEPARTMENT' && FirstFilterApplied !='DEPARTMENT') { let xx = UniqueListFromData(data, ''); fillSELECT(pref + 'DEPARTMENT', xx); } if (filterField != 'UO_DESC' && FirstFilterApplied !='UO_DESC') { let xx = UniqueListFromData(data, 'UO_DESC'); fillSELECT(pref + 'UO_DESC', xx); } if (filterField != 'LEVEL' && FirstFilterApplied !='LEVEL') { xx = UniqueListFromData(data, 'LEVEL'); fillSELECT(pref + 'LEVEL', xx); } if (filterField != 'LEVPROF' && FirstFilterApplied !='LEVPROF') { xx = UniqueListFromData(data, 'LEVPROF'); fillSELECT(pref + 'LEVPROF', xx); } }; }) $table.on('column-search.bs.table', function (e, name, args) { //Fired when we are searching into the column data if ((DataLoadedInTable == true && args != '') || FilterApplied1Time==true) { filterField = name; if (filterField == filterFirstApplied) { //This is executed when you choose the first SELECT type chosen var ctl=".bootstrap-table-filter-control-" + filterField ; var myval = GetSelectedOption(ctl); ResetInAction = true; var key = filterField; var newFilter = {}; newFilter[key] = myval; filterApplied=false; LastFilter = newFilter; $table.bootstrapTable('filterBy', newFilter) $(ctl + " option[value='" + myval + "']").attr('selected','selected'); filterApplied = true; myFilter[filterField] = (args != '' ? true : false); ResetInAction = false; return false; } switch (name) { case 'DEPARTMENT': case 'UO_DESC': case .....: filterApplied = true; myFilter[filterField] = (args != '' ? true : false); if (filterFirstApplied == '') {filterFirstApplied=name;}; break; default: } } }) $table.on('search.bs.table', function (name) { if ($(".bootstrap-table-filter-control-UO_DESC option:selected").text() == '') { myFilter.UO_DESC = false; }; if ($(".bootstrap-table-filter-control-DEPARTMENT option:selected").text() == '') { myFilter.DEPARTMENT = false; }; var data = $("#table").bootstrapTable('getData', { unfiltered: true, includeHiddenRows:true}); var b = Object.keys(myFilter).every((k) => !myFilter[k]); if (b == true) { FilterApplied=false; FilterApplied1Time=false; filterFirstApplied=''; } }); function UniqueListFromData(data, fieldName) { var xx = $.map(data, function (Field, e1) { return Field[fieldName]; }, []); var uniqueList = UniqueList(xx).sort(); return uniqueList; } function UniqueList(list) { var result = []; $.each(list, function (i, e) { if ($.inArray(e, result) == -1) result.push(e); }); return result; }
问题根源与修复方案
问题核心
执行filterBy方法时,Bootstrap-Table会重置所有筛选控件的状态,包括你刚选中的下拉框;同时后续page-change.bs.table事件中的填充逻辑可能误操作了当前已选中的筛选框,导致选中值被覆盖。
具体修复步骤
延迟设置选中状态,避免被内部事件覆盖
把设置选中状态的代码放到filterBy的回调函数中,确保在Bootstrap-Table内部状态更新完成后再执行:$table.bootstrapTable('filterBy', newFilter, function() { $(ctl).val(myval); // 用val()设置选中值比直接修改attr更可靠 });跳过当前活跃筛选框的填充逻辑
在page-change.bs.table事件中,只填充非当前筛选字段的下拉框,避免覆盖已选中的值:// 原逻辑修改为仅排除当前过滤字段 if (filterField !== 'DEPARTMENT') { let xx = UniqueListFromData(data, 'DEPARTMENT'); fillSELECT(pref + 'DEPARTMENT', xx); } if (filterField !== 'UO_DESC') { let xx = UniqueListFromData(data, 'UO_DESC'); fillSELECT(pref + 'UO_DESC', xx); } // 其他字段同理,去掉FirstFilterApplied的多余判断优化事件监听逻辑
直接监听page-change.bs.table事件,无需通过all.bs.table统一捕获,减少不必要的判断:$table.on('page-change.bs.table', function() { if (!DataLoadedInTable || !filterApplied) return; var pref = '.bootstrap-table-filter-control-'; var data = $("#table").bootstrapTable('getData', { unfiltered: false, includeHiddenRows:false}); if (filterField !== 'DEPARTMENT') { let xx = UniqueListFromData(data, 'DEPARTMENT'); fillSELECT(pref + 'DEPARTMENT', xx); } if (filterField !== 'UO_DESC') { let xx = UniqueListFromData(data, 'UO_DESC'); fillSELECT(pref + 'UO_DESC', xx); } if (filterField !== 'LEVEL') { xx = UniqueListFromData(data, 'LEVEL'); fillSELECT(pref + 'LEVEL', xx); } if (filterField !== 'LEVPROF') { xx = UniqueListFromData(data, 'LEVPROF'); fillSELECT(pref + 'LEVPROF', xx); } FilterApplied1Time = true; });修复
UniqueListFromData的空字段错误
原代码中UniqueListFromData(data, '')会尝试取Field[''],这是无效的,直接删除该分支或明确处理空字段场景。
内容的提问来源于stack exchange,提问作者Franco

