jquery DataTables 父行和子行作为一条记录而不是两条记录发布到服务器

Posted

技术标签:

【中文标题】jquery DataTables 父行和子行作为一条记录而不是两条记录发布到服务器【英文标题】:jquery DataTables parent and child rows posted to server as one record instead of two 【发布时间】:2019-02-18 04:44:33 【问题描述】:

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

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

普通(未调整大小)数据表:

目前我正在使用这个 jquery 函数将数据发布到服务器:

$('#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;
    );

但是当调整数据表的大小时,它会返回两行,然后将其发布到服务器。

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

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

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

父行示例:

<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 包含有效数据:

代码片段:

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>

【问题讨论】:

您能否在您的帖子中添加一个示例,说明父行和子行中的数据是什么? 您不能使用相对选择器来获取带有class="child" 的行,它是带有class="parent" 的行的下一个兄弟吗? @RyanWilson 看到上面的编辑。 @Dusan 那么看起来你根本不需要担心子行,所以只需检查一下是否有类为child的行,如果有的话使用parent 类获取行并使用它们发布,否则使用tr 获取行。 您的子行似乎只是在重复父行中的一些表单控件(例如,您有 2 个 Quantity 输入 - 但在父行中,它位于隐藏列中并且它具有没有价值) 【参考方案1】:

嗯,你真的不能。起初 DT 向 DOM 注入和删除子行及其内容,使它们对简单的 jQuery 选择器不可见。您可以定位打开的子行,但仅此而已。

其次,您不能成对选择多个元素。例如,您可以拥有 $('tr.parent, tr.parent ~ tr.child') 或类似名称,但这将等于 $('tr')。我会通过 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)
)

完全未经测试。请参阅JQuery Datatables search within input and select,了解如何在表单控件更改时更新 DT 内部。否则你只会得到返回默认值/原始值。

【讨论】:

以上是关于jquery DataTables 父行和子行作为一条记录而不是两条记录发布到服务器的主要内容,如果未能解决你的问题,请参考以下文章

jquery datatables 在表中显示产品链接

HTML:如何使用 AngularJs 填充第一行是父行和后续行是子行的行

●oracle——层次化查询

PowerQuery - 主行和子行 - 基于公式或逻辑的另一行的参考值

具有 Vue 语法的 jQuery DataTables 子行

选择所有子行都符合条件的父行