javascript - 使用 DataTables 在服务器端模式下具有单独搜索输入的多个表

标签 javascript php jquery ajax datatables

应用程序正在使用:

  • 数据表 1.10.18
  • jquery 3.2.1
  • PHP 后端
  • lodash 4.17.4

该应用程序包含一个由多个 数据表组成的网页。这些用途中的每一个 serverSide: true (服务器端模式)通过返回 JSON 数据的 ajax 端点获取数据。

表格初始化如下:

  1. 在页面上加载多个 <table>的被渲染。我正在使用 jquery .each()为每个初始化 DataTable:

    $.each($('table'), function () {
    
        $(this).DataTable({
            processing: true,
            serverSide: true,
            searching: false,
            ajax: {
                data: {
                   table_id: $(this).attr('id') 
            },
            url: '/get-data.json', 
        },
        ...
    });
    
  2. 每个 <table>有身份证。这是通过 data: 中的 ajax 传递的属性。端点 /get-data.json根据表 ID 返回数据。换句话说,它知道应该根据这个 ID 获取“哪个表”的数据。

我希望能够对表进行搜索,但必须在服务器端完成。为此,我在 (1) 中的初始化代码设置了 searching: false因为这有效地禁用了 DataTables 提供的客户端搜索功能(我们不能在这种情况下使用它,因为搜索必须在服务器端完成)。

我面临的问题是如何为每个表创建搜索输入、进行 ajax 调用并更新适当的表。我希望在输入 >=3 个字符后实时进行搜索。这个问题的关键是 1 个搜索输入负责搜索 1 个 DataTable - 它不是输入可以更新“页面上的任何/每个表”的搜索功能,这是其他常见描述的模式问题。 1 个输入:在这种情况下搜索 1 个表。

我的计划如下 - 第 (2) 点中引用的每个表都有一个 ID。我需要创建独特的输入。所以如果我有 ID 为 #table1 的表, #table2 , #table3我可以轻松创建:

<input type="text" name="table1_search" id="table1_search"> 
<input type="text" name="table2_search" id="table2_search"> 
<input type="text" name="table3_search" id="table3_search"> 

然后我检测输入是否发生了任何变化:

$('input[type="text"]').bind("keyup change input",
        function (e) {
            // Ignore tab key for keyup event otherwise it'll fire an ajax request that does nothing useful.
            if (e.which !== 9) {
                processSearch.call(this);
            } else {
                e.preventDefault();
            }
        });

    var prev_value = {};
    function processSearch() {
        var obj = $(this),
                search_id = obj.attr('id'), // ID of input
                search_value = obj.val(); // Value of input

        // There's been no change to the field, ignore.
        if (prev_value[search_id] === search_value) {
            return;
        }

        prev_value[search_id] = search_value;

        /* Wait until at least 3 characters have been entered, or user has cleared the input */
        if (search_value.length >= 3 || (!search_value)) {
            debouncedDraw({search_id: search_id, search_value: search_value});
        }
    }

上面的代码在等待输入 >=3 个字符方面满足了我的需要。然后我正在执行一个名为 debouncedDraw 的函数它传递一个包含 search_id 的对象和 search_value .这些分别指的是输入 ID 和值,例如如果我在 #table1_search 中输入“foo”那么对象是:

{search_id: 'table1_search', search_value: 'foo'}

debouncedDraw功能看起来像这样。这是使用 lodash限制函数触发的速率。这里的重点是根据我几年前在这里提出的一个问题来阻止它发出不必要的 ajax 请求:DataTables - kill ajax requests when a new one has started :

var debouncedDraw = _.debounce(function (opts) {
    console.log(opts);
}, 500);

目前这只是console.log上面给出的对象。

我不确定此时进行的最佳方式。我需要重新运行 /get-data.json通过 ajax,然后更新相应的表。

我可以访问请求数据并拆分 search_id根据下划线计算出数据用于哪个表 ID(例如 table1_search 目标 #table1 )。然后,我需要将此数据写回适当的表(在本例中为 #table1)。

我忍不住想我正在以一种令人费解的方式解决这个问题,并且想知道 DataTables 本身是否有更好的方法来支持它?这似乎是一个非常基本的要求(在 serverSide 模式下有多个可搜索表)。但我找不到任何具体介绍如何执行此操作的帖子。

最佳答案

我多年来遇到的所有“陷阱”都封装在下面的代码片段中。这是我在创建新数据表时经常使用的基本模板。使用此模式,您可以根据需要在页面上创建任意数量的数据表。

就我个人而言,我会为每个表使用不同的 ajax url 路径/路由,以便表逻辑位于后端的单独文件中……但是可以将所有数据逻辑放在一个后端文件中。我修改了我常用的模板以适应这种情况。


<script> //I usually put the script section in the head tag

var table_1; //declare your table var here and initialize as a datatable inside document ready below.

$(document).ready(function() {

    table_1 = $('#table_1').DataTable( {
        dom: "Bfrtip",
        ajax: {
            url: "/get-data.json?table=table_1",  //add query string var for backend routing
            type: "POST"  //use POST to not have to deal with url encoding various characters
        },      
        serverSide: true,
        searchDelay: 2000,  // use this instead of custom debounce
        processing: true, // optional visual indicator that a search has been sent to backend
        lengthMenu: [ 10, 25, 50, 75, 100 ], // define per page limits. first value will be the default
        buttons: [
            "pageLength" // per page drop down button. i usually override/extend the default button
        ],      
        columns: [ // column definitions of json data fields
            { data: "col_1", title: "ID", width: "1%" },  // width: 1% makes col width as small as possible
            { data: "col_2", title: "Label 2", visible:false }, //visible: false allows you access to field data without displaying to user
            { data: "col_3", title: "Label 3", render: function ( data, type, row ) { //render allows combining of fields into single column
                    return data + ' <small>('+row.col_2+')</small>'; // data will be col_3 value. row.col_2 is how you reference col_2 value
            } },
            { data: "col_4", title: "Label 4", searchable:false }, //searchable: false set this field to not be used in search
        ],
        rowId: 'col_1' //sets the tr row id to the value in this column. useful for DOM and other manipulation later
    } );
}

</script>

<table id="table_1" class="table table-striped table-bordered table-sm" style="width:100%"></table>

<!-- If you define title attributes in col definitions above you don't need to create html table headers/footers. Just an empty table tag will do. -->

通过这种模式,您可以利用数据表附带的内置搜索输入来处理您的用例,并在所有表上进行服务器端处理。

在我疯狂的背后有一个方法,我试图在每一行的脚本注释中记录下来。如果您对某事有疑问,请告诉我。我认为这是值得赏金的。

供引用,在使用数据表开发新应用程序时,我基本上住在这个页面 https://datatables.net/reference/option/

编辑 1

在您现有的去抖动 drawTable 函数中,您可以执行如下操作:

function drawTable(id) {
    $('#'+id).DataTable().ajax.url( 'get-data.json?table_id='+id+'&foo=bar' ); //update ajax url of existing dt - if necessary
    $('#'+id).DataTable().search(search_input_val).draw(); // fire ajax request with value from your custom search input

}

我相当确定您需要将“searching”设置为 true 才能使此方法起作用。

编辑2

刚刚想到的另一种方式,不用dt search。通过修改后的 url 和加载/重新加载来传递所有数据。

$('#'+id).DataTable().ajax.url( 'get-data.json?table_id='+id+'&search=foo' ).load();

如果您在输入字段上使用按钮点击监听器或 onblur 监听器并触发上面相同的命令,那么您可以摆脱所有的去抖动。

你见过吗? https://datatables.net/reference/api/%24.fn.dataTable.util.throttle()

我以前从未使用过它,但它看起来像一个去抖动。页面上的示例显示它用于 .search()

关于javascript - 使用 DataTables 在服务器端模式下具有单独搜索输入的多个表,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57972120/

相关文章:

javascript - innerText 和 html 的区别

javascript - 按下后退按钮时页面内容不会改变

javascript - 我试图弄清楚如何更改页面上显示的日期格式

javascript - 如何将部分数据转换为 HTML

javascript - 带淡入淡出的内联 block

C# WebBrowser 控件——在 AJAX 之后获取文档元素?

javascript - 从字符串运行方程

php - 无法在 Yii 1.x 的迁移中使用模型

PHP Mysql PDO和解锁表

jquery - 从事件触发器获取jqgrid DOM ID