在jQuery数据表中的特定位置添加新行

8

默认
我创建了一个ajax数据表格,有时候行是通过json在表格末尾填充的:jsfiddle,有时候则在表格顶部。这取决于ajax响应时间。

推荐输出
我有两个来自不同来源的输入json,输出是这个表格:

<table>
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>1</td><td>2</td><td>3</td></tr>
    ...
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>8</td><td>7</td><td>6</td></tr> <!-- inserted row-->
    <tr><td>8</td><td>7</td><td>6</td></tr> <!-- inserted row-->
    <tr><td>8</td><td>7</td><td>6</td></tr> <!-- inserted row-->
    <tr><td>8</td><td>7</td><td>6</td></tr> <!-- inserted row-->
    <tr><td>1</td><td>2</td><td>3</td></tr>
    <tr><td>1</td><td>2</td><td>3</td></tr>
    ...
    <tr><td>1</td><td>2</td><td>3</td></tr>
</table>

从第二个json中提取的行将被插入到特定位置的表中(该表由第一个json创建)。该位置是固定的,1号和2号json数据长度是不变的。

第一种解决方案
我需要添加第一列包含一个数字,并按其降序排序datatable - jsfiddle。我可以隐藏第一列jsfiddle,但我更愿意使用自定义函数,因为它不适用于IE8。

var t = $("#tab1").DataTable({
    "ajax": "data1.json",
    columnDefs: [
         { className: "hide", "targets": [ 0 ] },
         ], 
    "columns": [
        { "data": "id"},
        { "data": "cat1"},
        { "data": "cat2"},
        { "data": "cat3"}
    ]
});

$.ajax({
    type: "GET",
    url: "data2.json",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (response) {
        t.rows.add(response.data); 
        t.draw();
    }
  });

IDEA - 自定义函数
我尝试创建自定义函数rows.addinposition(rows, position),但它的作用与函数rows.add()相同。
我复制并修改了在jquery.dataTables.js中找到的函数rows.add(),位于第7879行,我将out.push()更改为out.splice()splice文档

我知道这样做不被推荐,最好是扩展datatables api...

_api_register( 'rows.addinposition()', function ( rows, position ) {
    var newRows = this.iterator( 'table', function ( settings ) {
            var row, i, ien;
            var out = [];

            for ( i=0, ien=rows.length ; i<ien ; i++ ) {
                row = rows[i];

                if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
                    //ROWS.ADD USE OUT.PUSH
                    //out.push( _fnAddTr( settings, row )[0] );
                    //CHANGED TO OUT.SPLICE
                    out.splice( position, 0, _fnAddTr( settings, row )[0] );
                }
                else {
                    out.splice( position, 0, _fnAddData( settings, row ) );
                }
            }
            console.log(out);
            return out;

        }, 1 );

    // Return an Api.rows() extended instance, so rows().nodes() etc can be used
    var modRows = this.rows( -1 );
    modRows.pop();
    modRows.push.apply( modRows, newRows.toArray() );

    return modRows;
} );    

希望你能帮助我。

我找到了类似的问题:

编辑
谢谢davidkonrad,但我在jsfiddle中测试它时发现了两个问题:

  • 排序错误,应为2、1而不是1、2。- 我认为这是一个简单的问题。
  • 有时这些添加的行会在表格顶部,有时在正确的位置。随机出现。- 可能是个大问题。

我在jsfiddle中进行了调试,它的行为非常奇怪:

console.log('rowCount = '+rowCount);

如果行在顶部(位置不好),返回:
rowCount = 0
rowCount = 1

由于Firebug不显示var i,因此for循环没有执行。

如果它们处于良好的位置,返回:

rowCount = 5
rowCount = 6

在此示例中使用了for循环和返回var i
1. 循环:

i = 5 
i = 4 
i = 3

2.loop:

i = 6 
i = 5 
i = 4 
i = 3

我错过了什么吗?为什么顺序很奇怪?


你能解释一下你想要实现什么吗?为什么需要在特定位置插入行,背后的原因是什么? - Gyrocode.com
我已经将推荐的输出添加到问题中。 - jezrael
仍然不清楚你为什么要这样做。让我们在聊天中继续讨论。http://chat.stackoverflow.com/rooms/84885/room-for-gyrocode-com-and-jezrael - Gyrocode.com
2个回答

6

您不需要直接修改源代码,而是使用 dataTable.Api.register

jQuery.fn.dataTable.Api.register('row.addByPos()', function(data, index) {     
    var currentPage = this.page();

    //insert the row  
    this.row.add(data);

    //move added row to desired index
    var rowCount = this.data().length-1,
        insertedRow = this.row(rowCount).data(),
        tempRow;

    for (var i=rowCount;i>=index;i--) {
        tempRow = this.row(i-1).data();
        this.row(i).data(tempRow);
        this.row(i-1).data(insertedRow);
    }     

    //refresh the current page
    this.page(currentPage).draw(false);
});

上述功能(或插件)插入行,然后通过交换内容使行向上移动到其所需位置,详细解释请参阅 -> 读取更详细的解释。 演示 -> http://jsfiddle.net/p4wcfzfe/ 由于该插件向通用API添加了一个函数,因此应在使用该函数的任何dataTable初始化之前声明插件。
{ plugin declaration }
var table = $("#example").DataTable();
table.row.addByPos([data], 1);

注意:你的“第一个解决方案”也应该在IE8中可用,请尝试删除尾逗号。

@jezrael,您正在尝试一次性插入多个新行,而函数每次只能处理一行(如果您查看代码,它只会将一个行从数组末尾移动到所需位置,而不是多个行)。您必须为每一行调用addByPos -> response.data.forEach(function(data) { t.row.addByPos(data, 1); })。分叉的fiddle -> http://jsfiddle.net/p4wcfzfe/ 或者修改addByPos以处理更复杂的数据类型。 - davidkonrad
不,table.row 应该是 this.row,抱歉打错了。 - davidkonrad
@jezrael,已经完成了。感谢您接受答案!我想我应该在第一次加入fiddle以防止打字错误,事实上答案已经在fiddle中进行了测试-> http://jsfiddle.net/anxw7063/ :( - davidkonrad
我在http://jsfiddle.net/jezrael/p4wcfzfe/1/中对它进行了测试,我只将位置更改为3。我发现2个问题:-排序是错误的(2.,1.),不是1.,2.并且有时这些添加的行位于表格顶部,有时处于正确的位置。 随机的 :( - jezrael
这个可以工作,但只适用于一行数据,它忽略了tr标签的属性,如class、id等。有没有办法让它移动整个“节点”,而不仅仅是数据? - Kevin P

3

解决方案

我认为您需要使用jQuery的$.when函数,在两个Ajax调用都成功时执行回调。

这样,您总是以相同的顺序获取数据,无需编写函数将数据插入特定位置。

此外,如果需要,在初始化数据表之前可以操作最终数据。例如,下面只显示了两个选项,可能性是无限的。

call2中的数据附加到call1中的数据:

var data = a1[0].data.concat(a2[0].data);

call2的数据插入到call1的第2个位置 (来源):

var data = a1[0].data;
data.splice.apply(data, [2, 0].concat(a2[0].data));

演示

请参阅下面的示例代码和演示。

$(document).ready(function(){
   var call1 = $.ajax({
      url: "https://api.myjson.com/bins/48g56",
      type: "GET",
      dataType: "json",
      contentType: "application/json; charset=utf-8",
   });

   var call2 = $.ajax({
      url: "https://api.myjson.com/bins/1bfa2",
      type: "GET",
      dataType: "json",
      contentType: "application/json; charset=utf-8",
   });
   
   
   // When both Ajax requests were successful
   $.when(call1, call2).done(function(a1, a2){
      // a1 and a2 are arguments resolved for the call1 and call2 ajax requests, respectively.
      // Each argument is an array with the following structure: [ data, statusText, jqXHR ]
     
      // Append data from call2 to data from call1
      // var data = a1[0].data.concat(a2[0].data);
     
      // Insert data from call2 at position 2 of data from call1
      var data = a1[0].data;
      data.splice.apply(data, [2, 0].concat(a2[0].data));
     
      // Initialize data table
      var t = $("#tab1").DataTable({
         data: data,
         columnDefs: [
            { className: "hide", "targets": [ 0 ] },
         ], 
         order: [],
         ordering: false,        
         columns: [
            { "data": "id"},
            { "data": "cat1"},
            { "data": "cat2"},
            { "data": "cat3"}
         ]
      });
   });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://cdn.datatables.net/1.10.7/js/jquery.dataTables.js"></script>
<link href="http://cdn.datatables.net/1.10.7/css/jquery.dataTables.css" rel="stylesheet"/>


<table id="tab1" class='data tab01'>
 <thead>
  <tr>
    <th>id</th>
            <th>cat1</th>
   <th>cat2</th>
   <th>cat3</th>
  </tr>
 </thead>
 <tbody>
 </tbody>
</table>


谢谢,但是排序有问题,因为在演示中没有"aaSorting": []。我创建了这个http://jsfiddle.net/7j19hj5s/16/,其中第一列“ordering”缺失,并且添加的行不幸地出现在表格的末尾。 - jezrael
@jezrael,我忘记在我的演示中禁用排序了。我之前提到过,如果你想让行始终保持在某个位置,那么你需要禁用排序,而你说过你会禁用它。 - Gyrocode.com
@jezrael,你可以随意操作结果a1a2,但重要的是你知道a1是第一次调用的结果,而a2是第二次调用的结果。让我更新答案并提供详细信息。 - Gyrocode.com

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接