jquery DataTables übergeordnete und untergeordnete Zeilen, die als ein Datensatz anstelle von zwei auf den Server gesendet werden


Dusan

Ich habe ein Problem beim jquery DataTablesErstellen von übergeordneten und untergeordneten Zeilen beim Ändern der Größe (responsive DataTable) und muss Werte von Eingaben aus untergeordneten Zeilen sowie aus übergeordneten Zeilen speichern und über Ajax an die Controller-Aktion senden.

Responsive (Größe geändert) DataTable:

Responsive DataTable

Normale Datentabelle (nicht in der Größe geändert):

Normale Datentabelle

Derzeit verwende ich diese jquery-Funktion, um Daten auf dem Server zu veröffentlichen:

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

Wenn die Größe der Datentabelle geändert wird, werden zwei Zeilen zurückgegeben, die wiederum auf dem Server veröffentlicht werden.

Ich rufe Zeilen aus einer Tabelle ab über:

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

Wie kann ich alle zugehörigen übergeordneten und untergeordneten Zeilen als eine Zeile abrufen, damit ich diese Zeile auf dem Server veröffentlichen kann?

Beispiel für eine übergeordnete Zeile:

<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>

Beispiel für eine untergeordnete Zeile:

<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>

Vom Controller gepostete Daten, index 0enthält gültige Daten:

Der Controller hat Daten gebucht

Code-Auszug:

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>

davidkonrad

Das kannst du wirklich nicht. Zuerst injiziert und entfernt DT untergeordnete Zeilen und deren Inhalt in und aus dem DOM, wodurch sie für einfache jQuery-Selektoren unsichtbar werden. Sie können auf offene untergeordnete Zeilen abzielen, aber das ist alles.

Zweitens können Sie nicht mehrere Elemente paarweise auswählen. Sie könnten zum Beispiel $('tr.parent, tr.parent ~ tr.child')oder ähnliches haben, aber das wäre gleich gleich $('tr'). Ich würde die API durchgehen:

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)
})

Völlig ungetestet. Siehe JQuery Datatables-Suche in Eingaben und wählen Sie aus, wie die DT-Interna aktualisiert werden sollen, wenn sich die Formularsteuerelemente ändern. Andernfalls erhalten Sie nur Standard- / Originalwerte zurück.

Verwandte Artikel