jQuery DataTables父行和子行作为一个记录而不是两个记录发布到服务器 [英] jquery DataTables parent and child rows posted to server as one record instead of two

查看:83
本文介绍了jQuery DataTables父行和子行作为一个记录而不是两个记录发布到服务器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个问题,其中jquery DataTables在调整大小(响应DataTable)时创建父行和子行,并且我需要保存子行以及父行的输入值,并通过Ajax发布到控制器操作.

I have a problem where jquery DataTables creates parent and child rows on resize (responsive DataTable) and I need to save values of inputs from child rows as well as from parent rows and post via ajax to controller action.

响应式(调整大小)数据表:

Responsive (resized) DataTable:

正常(未调整大小)数据表:

Normal (not resized) DataTable:

当前,我正在使用此jquery函数将数据发布到服务器:

Currently I am using this jquery function to post data to the server:

$('#SaveItemButton').click(function (e) {       
        var arr = [];       
        var rows = $('#ItemTable').find('tbody').find('tr');
        console.log(rows.length);       
        $.each(rows, function (index, item) {           
            var controls = $(this).find('input, select');    
            console.log(controls.length);            
            item = {
                ItemType: controls.eq(0).val(),
                Unit: controls.eq(1).val(),
                Quantity: controls.eq(2).val(),
                Price: controls.eq(3).val(),
                InvoiceDate: $('#InvoiceDate').val(),
                TransferDate: $('#TransferDate').val(),
                TransferPlace: $('#TransferPlace').val(),
                InvoiceDescription: $('#InvoiceDescription').val()
            };            
            arr.push(item);
        });

        $.ajax({
            url: '/Item/Add',
            data: JSON.stringify(arr),
            contentType: 'application/json',
            type: "POST",
            dataType: "json",
            success: function (result) {
                //alert(result);
            },
            error: function (errormessage) {                

            }
        });  
        return false;
    });

,但是当调整数据表的大小时,它返回两行,这些行又被发布到服务器.

but when the Datatable is resized it returns two rows which in turn gets posted to the server.

我正在通过以下方式从表中检索行:

I am retrieving rows from a table via:

var rows = $('#ItemTable').find('tbody').find('tr');

如何将所有相关的父行和子行作为一行,以便将该行发布到服务器?

How can I get all the related parent rows and child rows as one row so I can post that row to the server?

父行示例:

<tr role="row" class="odd parent">
    <td tabindex="0" style=""></td>
    <td class="sorting_1"><input name="ItemType" class="form-control" type="text"></td>
    <td style="display: none;"><select name="Unit" class="form-control defaultpicker"><option>dan</option><option>Komad</option><option>Sat</option>m<option>m2</option><option>m3</option><option>kg</option><option>lit</option><option>pak</option><option>reč</option></select></td>
    <td style="display: none;"><input name="Quantity" class="form-control" type="number"></td>
    <td style="display: none;"><input name="Price" class="form-control" type="text"></td>
    <td style="display: none;"><input name="Total" class="form-control" type="text" readonly=""></td>
    <td style="display: none;"><button type="submit" id="DeleteButton" class="fa fa-times select-row btn btn-secondary btn-sm" data-id=""></button>
    </td>
</tr>

子行示例:

<tr class="child">
    <td class="child" colspan="2">
        <ul data-dtr-index="0" class="dtr-details">
            <li data-dtr-index="2" data-dt-row="0" data-dt-column="2">
                <span class="dtr-title">Unit</span>
                <span class="dtr-data">
                    <select name="Unit" class="form-control defaultpicker"><option>dan</option><option>Komad</option><option>Sat</option>m<option>m2</option><option>m3</option><option>kg</option><option>lit</option><option>pak</option><option>reč</option></select>
                </span>
            </li>
            <li data-dtr-index="3" data-dt-row="0" data-dt-column="3">
                <span class="dtr-title">Quantity</span>
                <span class="dtr-data">
                    <input name="Quantity" class="form-control" type="number" value="3">
                </span>
            </li>
            <li data-dtr-index="4" data-dt-row="0" data-dt-column="4">
                <span class="dtr-title">Price</span>
                <span class="dtr-data">
                    <input name="Price" class="form-control" type="text" value="1000">
                </span>
            </li>
            <li data-dtr-index="5" data-dt-row="0" data-dt-column="5">
                <span class="dtr-title">Total</span>
                <span class="dtr-data">
                    <input name="Total" class="form-control" type="text" readonly="" value="">
                </span>
            </li>
            <li data-dtr-index="6" data-dt-row="0" data-dt-column="6">
                <span class="dtr-title"></span>
                <span class="dtr-data">
                    <button type="submit" id="DeleteButton" class="fa fa-times select-row btn btn-secondary btn-sm" data-id=""></button>
                </span>
            </li>
        </ul>
    </td>
</tr>

控制器发布的数据,index 0包含有效数据:

Controller posted data, index 0 contains valid data:

代码段:

var table = $('#ItemTable').DataTable({
  "dom": '<"toolbar">frtip',
  "paging": true,
  "pagingType": "full_numbers",
  "searching": false,
  // Solution to responsive table losing data
  'columnDefs': [{
    'targets': [1, 2, 3, 4, 5, 6],
    'render': function(data, type, row, meta) {
      if (type === 'display') {
        var api = new $.fn.dataTable.Api(meta.settings);

        var $el = $('input, select, textarea', api.cell({
          row: meta.row,
          column: meta.col
        }).node());

        var $html = $(data).wrap('<div/>').parent();

        if ($el.prop('tagName') === 'INPUT') {
          $('input', $html).attr('value', $el.val());
          if ($el.prop('checked')) {
            $('input', $html).attr('checked', 'checked');
          }
        } else if ($el.prop('tagName') === 'TEXTAREA') {
          $('textarea', $html).html($el.val());

        } else if ($el.prop('tagName') === 'SELECT') {
          $('option:selected', $html).removeAttr('selected');
          $('option', $html).filter(function() {
            return ($(this).attr('value') === $el.val());
          }).attr('selected', 'selected');
        }

        data = $html.html();
      }

      return data;
    }
  }],
  'responsive': true,
  order: [1, 'asc']
});

// Solution to responsive table losing data
$('#ItemTable tbody').on('keyup change', '.child input, .child select, .child textarea', function(e) {
  var $el = $(this);
  var rowIdx = $el.closest('ul').data('dtr-index');
  var colIdx = $el.closest('li').data('dtr-index');
  var cell = table.cell({
    row: rowIdx,
    column: colIdx
  }).node();
  $('input, select, textarea', cell).val($el.val());
  if ($el.is(':checked')) {
    $('input', cell).prop('checked', true);
  } else {
    $('input', cell).removeProp('checked');
  }
});

$('#SaveItemButton').click(function() {
  var arr = [];
  var rows = $('#ItemTable').find('tbody').find('tr');
  console.log(rows.length);
  $.each(rows, function(index, item) {
    var controls = $(this).find('input, select');
    console.log(controls.length);
    item = {
      ItemType: controls.eq(0).val(),
      Unit: controls.eq(1).val(),
      Quantity: controls.eq(2).val(),
      Price: controls.eq(3).val(),
      InvoiceDate: $('#InvoiceDate').val(),
      TransferDate: $('#TransferDate').val(),
      TransferPlace: $('#TransferPlace').val(),
      InvoiceDescription: $('#InvoiceDescription').val()
    };
    arr.push(item);
  });

  $.ajax({
    url: '/Item/Add',
    data: JSON.stringify(arr),
    contentType: 'application/json',
    type: "POST",
    dataType: "json",
    success: function(result) {
      //alert(result);
    },
    error: function(errormessage) {

    }
  });
  return false;
});

<link href="https://cdn.datatables.net/1.10.16/css/jquery.dataTables.min.css" rel="stylesheet" />
<link href="https://cdn.datatables.net/responsive/2.2.3/css/responsive.dataTables.min.css" rel="stylesheet" />


<table id="ItemTable" class="table table-hover table-secondary dataTable no-footer dtr-inline" style="width: 100%;" role="grid" aria-describedby="ItemTable_info">
  <thead>
    <tr role="row">
      <th></th>
      <th>ItemType</th>
      <th>Unit</th>
      <th>Quantity</th>
      <th>Price</th>
      <th>Total</th>
      <th></th>
    </tr>
  </thead>
  <tbody>
    <tr role="row" class="odd parent">
      <td tabindex="0" style=""></td>
      <td class="sorting_1"><input name="ItemType" class="form-control" type="text"></td>
      <td style="">
        <select name="Unit" class="form-control defaultpicker">
          <option>value1</option>
          <option>value2</option>
          <option>value3</option>
          <option>value4</option>
          <option>value5</option>
          <option>value6</option>
          <option>value7</option>
          <option>value8</option>
          <option>value9</option>
        </select>
      </td>
      <td style=""><input name="Quantity" class="form-control" type="number"></td>
      <td style=""><input name="Price" class="form-control" type="text"></td>
      <td style=""><input name="Total" class="form-control" type="text" readonly=""></td>
      <td style=""><button type="submit" id="DeleteButton" data-id=""></button></td>
    </tr>
  </tbody>
</table>


<script src="https://code.jquery.com/jquery-3.3.1.min.js" integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=" crossorigin="anonymous"></script>
<script src="https://cdn.datatables.net/1.10.16/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/buttons/1.5.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/select/1.2.6/js/dataTables.select.min.js"></script>
<script src="https://cdn.datatables.net/responsive/2.2.3/js/dataTables.responsive.min.js"></script>

推荐答案

好吧,您真的不能.最初,DT向DOM注入子行及其内容并从DOM中删除子行及其内容,从而使它们对于简单的jQuery选择器不可见.您可以定位打开的子行,仅此而已.

Well, you really cannot. At first DT inject and remove child rows and their content to and from the DOM, making them invisible to simple jQuery selectors. You can target open child rows, but that is all.

第二,您不能成对选择多个元素.例如,您可能有$('tr.parent, tr.parent ~ tr.child')或类似名称,但这仅等于$('tr').我将通过API:

Secondly you cannot select multiple elements in pairs. You could have for example $('tr.parent, tr.parent ~ tr.child') or similar, but that would be equal to just $('tr'). I would go through the API:

table.rows().every(function() {
  var $node = this.nodes().to$();
  var item = {
    ItemType: $node.find('input[name=ItemType]').val(),
    Unit: $node.find('select[name=Unit]').val(),
    Quantity: $node.find('input[name=Quantity]').val(),
    Price: $node.find('input[name=Price]').val(),
    Total: $node.find('input[name=Total]').val(),
    InvoiceDate: $('#InvoiceDate').val(),
    TransferDate: $('#TransferDate').val(),
    TransferPlace: $('#TransferPlace').val(),
    InvoiceDescription: $('#InvoiceDescription').val()
  };
  arr.push(item)
})

完全未经测试.有关如何更新DT的信息,请参见 JQuery Datatables搜索并选择.表单控件更改时的内部结构.否则,您将只获得返回默认值/原始值.

Completely untested. See JQuery Datatables search within input and select on how to update the DT internals when form controls is changing. Otherwise you will just get return default / original values.

这篇关于jQuery DataTables父行和子行作为一个记录而不是两个记录发布到服务器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆