You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何让jQuery DataTable筛选后仅显示可见列数据于筛选下拉菜单

解决jQuery DataTable筛选下拉菜单仅显示可见行数据的问题

问题说明

运行提供的代码后,jQuery DataTable的每列表头带有筛选图标,点击会弹出含复选框的下拉菜单显示该列所有值。但当筛选某列导致数据减少后,点击其他列的筛选图标,下拉菜单仍显示该列全部原始值(包含已被过滤的条目),需求是让筛选菜单仅展示当前可见行对应列的数据。

解决方案

核心是每次打开筛选菜单时,动态从当前可见行中提取目标列的唯一值,而非初始化时一次性生成固定的复选框列表。具体修改步骤如下:

  1. 移除configFilter中生成筛选菜单内容的逻辑,仅保留添加筛选图标的代码
  2. 修改showFilter函数,每次打开菜单时重新获取当前可见行数据,生成对应列的唯一值复选框
  3. 优化唯一值去重逻辑,确保菜单中只显示当前可见的列值

修改后的完整代码

<!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>

修改关键点说明

  1. configFilter函数:仅负责添加表头筛选图标和初始化空的筛选菜单模板,不再预生成复选框列表
  2. showFilter函数:
    • 使用table.rows({search:'applied'}).data()获取当前经过筛选后的可见行数据
    • 提取目标列的值并去重,动态生成复选框内容插入菜单
  3. performFilter和clearFilter函数:执行操作后清空菜单中的复选框内容,确保下次打开时重新生成最新的可见值列表

内容的提问来源于stack exchange,提问作者KitKat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 13:23:13