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

应用程序正在使用:

  • 数据表 1.10.18

  • jQuery 3.2.1

  • PHP 后端

  • lodash 4.17.4

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

表初始化如下:


在页面加载<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', 

    },

    ...

});

每个<table>人都有一个 ID。这是通过data:属性中的 ajax 传递的。端点/get-data.json根据表 ID 返回数据。换句话说,它知道应该根据这个 ID 为“哪个表”获取数据。


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


我面临的问题是如何为每个表创建搜索输入、进行 ajax 调用并更新相应的表。我希望在输入 >=3 个字符后实时搜索。这个问题的关键是 1 个搜索输入负责搜索 1 个数据表 - 它不是一个搜索功能,输入可以更新“页面上的任何/每个表”,这是其他问题中常见的模式。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"> 


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


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

debouncedDraw函数看起来像这样。这是使用lodash来限制函数可以触发的速率。这里的重点是根据我几年前在这里提出的一个问题来阻止它发出不必要的 ajax 请求:DataTables - 当一个新请求开始时终止 ajax 请求:


var debouncedDraw = _.debounce(function (opts) {

    console.log(opts);

}, 500);

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


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


我可以访问请求数据并根据下划线拆分数据search_id以计算出数据用于哪个表 ID(例如table1_searchtargets #table1)。然后我需要将这些数据写回适当的表(#table1在这种情况下)。


我忍不住想我会以一种复杂的方式来解决这个问题,并想知道 DataTables 本身是否有更好的方法来支持这一点?这似乎是一个非常基本的要求(serverSide模式下的多个可搜索表)。但我找不到任何具体提到如何做到这一点的帖子。


ITMISS
浏览 215回答 2
2回答

慕神8447489

我多年来经历的所有“陷阱”都包含在下面的片段中。这是我在创建新数据表时经常使用的基本模板。您可以使用此模式在页面上创建任意数量的数据表。就个人而言,我会为每个表使用不同的 ajax url 路径/路由,以便表逻辑位于后端的单独文件中......但可以将所有数据逻辑放在一个后端文件中。我修改了我常用的模板以适应它。<script> //I usually put the script section in the head tagvar table_1; //declare your table var here and initialize as a datatable inside document ready below.$(document).ready(function() {&nbsp; &nbsp; table_1 = $('#table_1').DataTable( {&nbsp; &nbsp; &nbsp; &nbsp; dom: "Bfrtip",&nbsp; &nbsp; &nbsp; &nbsp; ajax: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url: "/get-data.json?table=table_1",&nbsp; //add query string var for backend routing&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; type: "POST"&nbsp; //use POST to not have to deal with url encoding various characters&nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; serverSide: true,&nbsp; &nbsp; &nbsp; &nbsp; searchDelay: 2000,&nbsp; // use this instead of custom debounce&nbsp; &nbsp; &nbsp; &nbsp; processing: true, // optional visual indicator that a search has been sent to backend&nbsp; &nbsp; &nbsp; &nbsp; lengthMenu: [ 10, 25, 50, 75, 100 ], // define per page limits. first value will be the default&nbsp; &nbsp; &nbsp; &nbsp; buttons: [&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; "pageLength" // per page drop down button. i usually override/extend the default button&nbsp; &nbsp; &nbsp; &nbsp; ],&nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; columns: [ // column definitions of json data fields&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { data: "col_1", title: "ID", width: "1%" },&nbsp; // width: 1% makes col width as small as possible&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { data: "col_2", title: "Label 2", visible:false }, //visible: false allows you access to field data without displaying to user&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { data: "col_3", title: "Label 3", render: function ( data, type, row ) { //render allows combining of fields into single column&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return data + ' <small>('+row.col_2+')</small>'; // data will be col_3 value. row.col_2 is how you reference col_2 value&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; } },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; { data: "col_4", title: "Label 4", searchable:false }, //searchable: false set this field to not be used in search&nbsp; &nbsp; &nbsp; &nbsp; ],&nbsp; &nbsp; &nbsp; &nbsp; rowId: 'col_1' //sets the tr row id to the value in this column. useful for DOM and other manipulation later&nbsp; &nbsp; } );}</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在现有的 debounced drawTable 函数中,您可以执行以下操作:function drawTable(id) {&nbsp; &nbsp; $('#'+id).DataTable().ajax.url( 'get-data.json?table_id='+id+'&foo=bar' ); //update ajax url of existing dt - if necessary&nbsp; &nbsp; $('#'+id).DataTable().search(search_input_val).draw(); // fire ajax request with value from your custom search input}我相当确定您需要将“搜索”设置为 true,但此方法才能正常工作。编辑 2我刚刚想到的另一种方式,不使用 dt 搜索。通过修改后的 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()

繁星淼淼

我已经实现了以下内容,但更喜欢更好的解决方案,因为我认为这不是有效的,而且绝对不是优雅的!从问题中获取代码,我修改了 debounce 函数,如下所示:var debouncedDraw = _.debounce(function (opts) {&nbsp; &nbsp;// Destroy the existing DataTable.&nbsp;&nbsp; &nbsp;$('#' + opts.search_region).DataTable().destroy();&nbsp;&nbsp; &nbsp;// Re-run the drawTable method to get the new DataTable with the search results&nbsp; &nbsp;drawTable(opts.search_region);}, 500);我介绍了一个名为的函数drawTable,它获取 a 的 ID<table>并运行 DataTables 初始化代码。还修改了 ajax 对象以考虑输入到给定表 ID 的搜索关键字输入中的任何内容:function drawTable(id) {&nbsp; &nbsp; $id = $('#'+id); // Convert string ID to jquery identifier&nbsp; &nbsp; $id.DataTable({&nbsp; &nbsp; &nbsp; &nbsp; // DataTable initialisation code as per question&nbsp; &nbsp; &nbsp; &nbsp; ajax: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; data: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;table_id: id,&nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;keywords: $('input[name="keywords_' + id + '"]').val() // search keywords for table_id&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; url: '/get-data.json',&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; // ... code as per question&nbsp; &nbsp; });}已$.each()修改,以便它检测每个<table>页面加载的 ID 并调用drawTable:$.each($('table'), function () {&nbsp; &nbsp; drawTable($(this).attr('id'));});这“有效”是因为它在页面加载时创建每个所需的 DataTable,并且还处理搜索。搜索输入名称已修改为以下格式:keywords_加上表的 ID,例如keywords_table1.我认为这不是有效的,因为我不得不调用destroy我的 DataTable。根据文档:这会对页面的性能造成非常显着的影响,因为涉及到大量的计算和 DOM 操作,所以如果您可以避免这种情况并使用 API,那么我们强烈建议您这样做!但是,我这样做的原因也与相同的文档中给出的相同:DataTables 不允许在初始化时以外的任何时间更改初始化选项。初始化后对表的任何操作都必须通过 API 完成好吧,我没有使用客户端搜索功能,因为我必须在服务器端进行搜索。所以我不确定通过 API 操作表格是否真的会在这种情况下有所帮助。有没有更好的方法来实现这一目标?
打开App,查看更多内容
随时随地看视频慕课网APP