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

DataTables.js过滤后按钮失效:如何维持事件监听?

问题:DataTables过滤后切换详情的按钮失效

我在ASP.NET Core项目里用DataTables.js展示机器列表,支持数据过滤,每行的按钮可以切换下方详情框的显示。初始状态下功能正常,但过滤之后按钮就失效了。

简化示例代码

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.5/css/jquery.dataTables.min.css">
    <style>
        
        .table-flexible th, .table-flexible td {
            text-align: center;
            vertical-align: middle;
            padding: 8px 16px;
        }
        .btn {
            font-size: 17px;
            padding: 2px;
        }
        .details-row {
            display: none;
        }
        .details-box {
            padding: 10px;
            background-color: #f9f9f9;
            border: 1px solid #ddd;
            border-radius: 5px;
        }
    </style>
</head>
<body>

<div class="form-group">
    <label for="machineFilter">Filter by Machine:</label>
    <select id="machineFilter" class="form-control" style="width: 20%; font-weight: normal">
        <option value="">All Machines</option>
        <!-- Example static options -->
        <option value="Machine1">Machine1</option>
        <option value="Machine2">Machine2</option>
    </select>
</div>

<table class="table table-striped table-flexible">
    <thead>
        <tr>
            <th>Machine</th>
            <th>Description</th>
            <th>Action</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>Machine1</td>
            <td>Details about Machine1</td>
            <td><button class="btn btn-info toggle-btn" data-target="#details1">Details</button></td>
        </tr>
        <tr id="details1" class="details-row">
            <td colspan="3">
                <div class="details-box">
                    Detailed information about Machine1.
                </div>
            </td>
        </tr>
        <tr>
            <td>Machine2</td>
            <td>Details about Machine2</td>
            <td><button class="btn btn-info toggle-btn" data-target="#details2">Details</button></td>
        </tr>
        <tr id="details2" class="details-row">
            <td colspan="3">
                <div class="details-box">
                    Detailed information about Machine2.
                </div>
            </td>
        </tr>
    </tbody>
</table>

<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<script>
    $(document).ready(function() {
        // Initialize DataTable
        var table = $('.table-flexible').DataTable({
         columnDefs: [{
                    "defaultContent": "-",
                    "targets": "_all"
                }],
            paging: false,
            ordering: false,
            info: false,
            dom: 'ft'
        });

        // Custom filter for Machine
        $('#machineFilter').on('change', function () {
            var selectedMachine = $(this).val();
            if (selectedMachine) {
                table.column(0).search('^' + selectedMachine + '$', true, false).draw();
            } else {
                table.column(0).search('').draw();
            }
        });

        // Attach event listener to buttons after filtering
        table.on('draw', function() {
            attachToggleEventListeners();
        });

        attachToggleEventListeners();  // Initial attachment of event listeners

        function attachToggleEventListeners() {
            $('.toggle-btn').off('click').on('click', function() {
                var target = $(this).data('target');
                $(target).fadeToggle(500); // Toggle the visibility of the target row
            });
        }
    });
</script>

</body>
</html>

按钮在过滤前完全可用,但用下拉框过滤后,按钮没法再切换详情框的可见性。怎么确保DataTables过滤后按钮还能正常工作?


更新说明

之前的解决方案适用于上面的示例代码,但示例没准确反映我的实际项目。以下是我.NET项目里的真实代码简化版:

@{ 

// Sample machine names
var MachineNames = new List<string> { "Machine A", "Machine B", "Machine C" };



// Sample requests using anonymous objects
var requests = new[]
{
new { Id = 1, ContactName = "Client A", CompanyName = "Machine A", Status = "Pending", Msg = "Request 1" },
new { Id = 2, ContactName = "Client B", CompanyName = "Machine B", Status = "In Progress", Msg = "Request 2" },
new { Id = 3, ContactName = "Client C", CompanyName = "Machine C", Status = "Completed", Msg = "Request 3" }
};

}


<div class="form-group">
    <label for="machineFilter">Filter by Machine:</label>
    <select id="machineFilter" class="form-control" style="width: 20%; font-weight: normal">
        <option value="">All Machines</option>
        @foreach (var machine in MachineNames)
        {
        <option value="@machine">@machine</option>
        }
    </select>
</div>

<table class="table table-striped table-flexible">
    <thead class="thead-custom">
    <tr>
        <th>Client</th>
        <th>Machine</th>
        <th>Status</th>
        <th>Description</th>
        <th>Actions</th>
    </tr>
    </thead>
    <tbody>
    @foreach (var request in requests)
    {
    <tr>
        <td>@request.ContactName</td>
        <td>@request.CompanyName</td>
        <td>@request.Status</td>
        <td>@request.Msg</td>
        <td>
            <button class="btn btn-info btn-sm toggle-btn" data-target="#detailsCollapse_@request.Id">
                Details
            </button>
        </td>
    </tr>
    <tr id="detailsCollapse_@request.Id" class="details-row" style="display: none;">
        <td colspan="5">
            <div class="card details-card">
                <button class="btn btn-success btn-sm mark-seen-btn" data-id="@request.Id">Mark as Seen</button>
            </div>
        </td>
    </tr>
    }
    </tbody>
</table>


@section Scripts
{
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<script>
    $(document).ready(function() {
        var table = $('.table-flexible').DataTable({
            columnDefs: [{
                "defaultContent": "-",
                "targets": "_all"
            }],
            paging: false,
            ordering: false,
            info: false,
            dom: 'ft'
        });

        // Custom filter for Machine
        $('#machineFilter').on('change', function () {
            var selectedMachine = $(this).val();
            if (selectedMachine) {
                table.column(1).search( selectedMachine, true, false).draw();
            } else {
                table.column(1).search('').draw();
            }
        });

        // Attach event listeners
        function attachEventListeners() {
            $('.toggle-btn').off('click').on('click', function() {
                var target = $(this).data('target');
                $(target).fadeToggle(500);
            });

            $('.mark-seen-btn').off('click').on('click', function() {
                var id = $(this).data('id');
                alert('Marked as seen: ' + id);
            });
        }

        // Reattach event listeners after each table draw
        table.on('draw', function() {
            attachEventListeners();
        });

        // Initial attachment of event listeners
        attachEventListeners();
    });
</script>

}

解决方案

问题核心是:DataTables过滤时会重新渲染DOM元素,原有直接绑定的事件会丢失;同时你的详情行未被DataTables识别为关联行,过滤后可能脱离DOM或无法被正确匹配。

修复代码(针对真实项目)

替换原有脚本部分即可:

@section Scripts
{
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdn.datatables.net/1.10.5/js/jquery.dataTables.min.js"></script>
<script>
    $(document).ready(function() {
        var table = $('.table-flexible').DataTable({
            columnDefs: [{
                "defaultContent": "-",
                "targets": "_all"
            }],
            paging: false,
            ordering: false,
            info: false,
            dom: 'ft',
            // 配置DataTables识别详情行为数据行的子行
            createdRow: function(row, data, dataIndex) {
                var nextRow = $(row).next();
                if (nextRow.hasClass('details-row')) {
                    table.row(row).child(nextRow).show();
                    nextRow.hide();
                }
            }
        });

        // 机器过滤逻辑
        $('#machineFilter').on('change', function () {
            var selectedMachine = $(this).val();
            if (selectedMachine) {
                table.column(1).search(selectedMachine, true, false).draw();
            } else {
                table.column(1).search('').draw();
            }
        });

        // 用事件委托绑定按钮事件,无需重复绑定
        $('.table-flexible').on('click', '.toggle-btn', function() {
            var target = $(this).data('target');
            $(target).fadeToggle(500);
        });

        $('.table-flexible').on('click', '.mark-seen-btn', function() {
            var id = $(this).data('id');
            alert('Marked as seen: ' + id);
        });
    });
</script>
}

关键改进点

  • 事件委托:将事件绑定到表格容器上,利用事件冒泡处理动态生成的按钮,避免每次渲染后重复绑定事件。
  • DataTables子行配置:通过createdRow回调把详情行关联到对应的数据行,确保过滤时详情行和数据行同步显示/隐藏。

修改后,无论过滤多少次,按钮功能都能正常生效。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.19 07:02:04