如何让jQuery DataTable筛选后仅显示可见列数据于筛选下拉菜单
解决jQuery DataTable筛选下拉菜单仅显示可见行数据的问题
问题说明
运行提供的代码后,jQuery DataTable的每列表头带有筛选图标,点击会弹出含复选框的下拉菜单显示该列所有值。但当筛选某列导致数据减少后,点击其他列的筛选图标,下拉菜单仍显示该列全部原始值(包含已被过滤的条目),需求是让筛选菜单仅展示当前可见行对应列的数据。
解决方案
核心是每次打开筛选菜单时,动态从当前可见行中提取目标列的唯一值,而非初始化时一次性生成固定的复选框列表。具体修改步骤如下:
- 移除
configFilter中生成筛选菜单内容的逻辑,仅保留添加筛选图标的代码 - 修改
showFilter函数,每次打开菜单时重新获取当前可见行数据,生成对应列的唯一值复选框 - 优化唯一值去重逻辑,确保菜单中只显示当前可见的列值
修改后的完整代码
<!DOCTYPE html> <html lang="en"> <head> <title>Jquery DataTable with Custom Filter</title> <link href="https://cdn.datatables.net/1.10.12/css/jquery.dataTables.min.css" type="text/css" rel="stylesheet" media="screen,projection" /> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/css/materialize.min.css" /> <script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script> <script src="https://cdn.datatables.net/1.10.12/js/jquery.dataTables.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.97.7/js/materialize.min.js"> </script> <style> table.dataTable th { border-bottom: 1px solid #333; border-right: 1px solid #333; } table.dataTable td { border-bottom: 1px solid #333; border-right: 1px solid #333; } .filterIcon { height: 16px; width: 16px; } .modalFilter { display: none; height: auto; background: #FFF; border: solid 1px #ccc; padding: 8px; position: absolute; z-index: 1001; } .modalFilter .modal-content { max-height: 250px; overflow-y: auto; } .modalFilter .modal-footer { background: #FFF; height: 35px; padding-top: 6px; } .modalFilter .btn { padding: 0 1em; height: 28px; line-height: 28px; text-transform: none; } #mask { display: none; background: transparent; position: fixed; left: 0; top: 0; z-index: 1; width: 100%; height: 100%; opacity: 1000; } </style> <script> $(document).ready(function () { var dataSet = [ ["Tiger Nixon", "System Architect", "Edinburgh", "5421", "2011/04/25", "$320,800"], ["Garrett Winters", "Accountant", "Tokyo", "8422", "2011/07/25", "$170,750"], ["Ashton Cox", "Junior Technical Author", "San Francisco", "1562", "2009/01/12", "$86,000"], ["Cedric Kelly", "Senior Javascript Developer", "Edinburgh", "6224", "2012/03/29", "$433,060"], ["Airi Satou", "Accountant", "Tokyo", "5407", "2008/11/28", "$162,700"] ]; $('#example').DataTable({ data: dataSet, "lengthMenu": [[5, 10, 50, -1], [5, 10, 50, "All"]], "pageLength": 10, columns: [ { title: "Name" }, { title: "Position" }, { title: "Office" }, { title: "Extn." }, { title: "Start date" }, { title: "Salary" } ], initComplete: function () { configFilter(this, [0, 1, 2, 4]); } }); $('#example_length,#example_filter').hide(); }); //初始化筛选图标,不再预生成筛选菜单内容 function configFilter($this, colArray) { setTimeout(function () { var tableName = $this[0].id; $.each(colArray, function (i, arg) { $('#' + tableName + ' th:eq(' + arg + ')').append('<img src="http://www.icone-png.com/png/39/38556.png" class="filterIcon" onclick="showFilter(event,\'' + tableName + '_' + arg + '\')" />'); }); //仅初始化空的筛选菜单模板 var template = '<div class="modalFilter">' + '<div class="modal-content">' + '<input type="text" class="filterSearchText" onkeyup="filterValues(this)" /> <br/>' + '</div>' + '<div class="modal-footer">' + '<a href="#!" onclick="clearFilter(this, {1}, \'{2}\');" class=" btn left waves-effect waves-light">Clear</a>' + '<a href="#!" onclick="performFilter(this, {1}, \'{2}\');" class=" btn right waves-effect waves-light">Ok</a>' + '</div>' + '</div>'; $.each(colArray, function (index, value) { var newTemplate = $(template.replace('{1}', value).replace('{2}', $this[0].id)); $('body').append(newTemplate); modalFilterArray[$this[0].id + "_" + value] = newTemplate; }); }, 50); } var modalFilterArray = {}; //打开筛选菜单时动态生成当前可见行的列值复选框 function showFilter(e, index) { $('.modalFilter').hide(); var modal = $(modalFilterArray[index]); modal.css({ left: 0, top: 0 }); var th = $(e.target).parent(); var pos = th.offset(); modal.width(th.width() * 0.75); modal.css({ 'left': pos.left, 'top': pos.top }); //解析表格ID和列索引 var [tableId, colIndex] = index.split('_'); colIndex = parseInt(colIndex); var table = $('#' + tableId).DataTable(); //获取当前可见行的目标列数据并去重 var distinctValues = []; table.rows({search:'applied'}).data().each(function(row){ var value = row[colIndex]; if(!distinctValues.includes(value)){ distinctValues.push(value); } }); //生成复选框内容 var content = ''; var columnName = table.column(colIndex).header().textContent.replace(/\s+/g, "_"); distinctValues.forEach(function(value, idx){ var checkboxId = tableId + "_" + columnName + "_" + idx; content += '<div><input type="checkbox" value="' + value + '" id="' + checkboxId + '"/><label for="' + checkboxId + '"> ' + value + '</label></div>'; }); //替换菜单内容 modal.find('.modal-content').find('br').after(content); modal.show(); $('#mask').show(); e.stopPropagation(); } //筛选复选框的搜索功能 function filterValues(node) { var searchString = $(node).val().toUpperCase().trim(); var rootNode = $(node).parent(); if (searchString == '') { rootNode.find('div').show(); } else { rootNode.find("div").hide(); rootNode.find("div:contains('" + searchString + "')").show(); } } //执行列筛选 function performFilter(node, i, tableId) { var rootNode = $(node).parent().parent(); var searchString = '', counter = 0; rootNode.find('input:checkbox').each(function (index, checkbox) { if (checkbox.checked) { searchString += (counter == 0) ? checkbox.value : '|' + checkbox.value; counter++; } }); $('#' + tableId).DataTable().column(i).search( searchString, true, false ).draw(); rootNode.hide(); $('#mask').hide(); //清空当前菜单内容,下次打开重新生成 rootNode.find('.modal-content').find('div').remove(); } //清除列筛选 function clearFilter(node, i, tableId) { var rootNode = $(node).parent().parent(); rootNode.find(".filterSearchText").val(''); rootNode.find('input:checkbox').each(function (index, checkbox) { checkbox.checked = false; $(checkbox).parent().show(); }); $('#' + tableId).DataTable().column(i).search( '', true, false ).draw(); rootNode.hide(); $('#mask').hide(); //清空当前菜单内容,下次打开重新生成 rootNode.find('.modal-content').find('div').remove(); } </script> </head> <body> <div id="mask"></div> <h3>Jquery DataTable with custom filter</h3> <table id="example" class="bordered material-table centered striped green lighten-1"></table> </body> </html>
修改关键点说明
configFilter函数:仅负责添加表头筛选图标和初始化空的筛选菜单模板,不再预生成复选框列表showFilter函数:- 使用
table.rows({search:'applied'}).data()获取当前经过筛选后的可见行数据 - 提取目标列的值并去重,动态生成复选框内容插入菜单
- 使用
performFilter和clearFilter函数:执行操作后清空菜单中的复选框内容,确保下次打开时重新生成最新的可见值列表
内容的提问来源于stack exchange,提问作者KitKat
相关产品推荐
相关产品推荐

