Search code examples
javascripthtmljquerydatatablesexpand

Not able to add information to child row of DataTables when clicking expand all


I am trying to add data based on the parent row to the child row. When I click on expand all, I want to be able to add data to the child based on the parent. When I click on the button all the rows open but the container is only added to the first row with the information of the last row on the current page of the datatable

Here is my example:

/* Formatting function for row details - modify as you need */
function format ( d ) {
    // `d` is the original data object for the row
    return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">'+
        '<tr>'+
            '<td>Full name:</td>'+
            '<td>'+d.name+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Extension number:</td>'+
            '<td>'+d.extn+'</td>'+
        '</tr>'+
        '<tr>'+
            '<td>Extra info:</td>'+
            '<td>And any further details here (images etc)...</td>'+
        '</tr>'+
    '</table>';
}

$(document).ready(function() {
    var table = $('#example').DataTable({
        'ajax': 'https://gyrocode.github.io/files/jquery-datatables/objects.json',
        'columns': [
            {
                'className':      'details-control',
                'orderable':      false,
                'data':           null,
                'defaultContent': ''
            },
            { 'data': 'name' },
            { 'data': 'position' },
            { 'data': 'office' },
            { 'data': 'salary' }
        ],
        'order': [[1, 'asc']]
    } );

    // Add event listener for opening and closing details
    $('#example tbody').on('click', 'td.details-control', function(){
        var tr = $(this).closest('tr');
        var row = table.row( tr );

        if(row.child.isShown()){
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        } else {
            // Open this row
            row.child(format(row.data())).show();
            tr.addClass('shown');
        }
    });

    // Handle click on "Expand All" button
    // Handle click on "Expand All" button
    $('#btn-show-all-children').on('click', function(){
        let containers, user_name;
        table.rows().every(function(){
            if(!this.child.isShown()){
              $('#example tbody>tr').each(function() {
                user_name = $(this).find('.sorting_1').text();
                containers = document.createElement('div');
                containers.setAttribute('id', `container_${user_name.replace(' ', '_')}`);
                $(`#container_${user_name.replace(' ', '_')}`).text(user_name);
              });
               this.child(containers).show();
                $(this.node()).addClass('shown');
            }
        });
    });

    // Handle click on "Collapse All" button
    $('#btn-hide-all-children').on('click', function(){
        // Enumerate all rows
        table.rows().every(function(){
            // If row has details expanded
            if(this.child.isShown()){
                // Collapse row details
                this.child.hide();
                $(this.node()).removeClass('shown');
            }
        });
    });
});
td.details-control {
    background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_open.png') no-repeat center center;
    cursor: pointer;
}
tr.shown td.details-control {
    background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_close.png') no-repeat center center;
}
<link rel='stylesheet' type='text/css' href='https://cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css'>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>

<button id="btn-show-all-children" type="button">Expand All</button>
<button id="btn-hide-all-children" type="button">Collapse All</button>
<hr>
<table id="example" class="display" cellspacing="0" width="100%">
    <thead>
        <tr>
                    <th></th>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Salary</th>
        </tr>
    </thead>
    <tfoot>
        <tr>
                    <th></th>
            <th>Name</th>
            <th>Position</th>
            <th>Office</th>
            <th>Salary</th>
        </tr>
    </tfoot>
</table>

As you can see, when you click on expand all. Each of the rows is supposed to have a container with the name in the parent. In the screenshot below you can see Airi Satou's child div has the name Cedric Kelly. Why is that happening?

enter image description here


Solution

  • As you have use .each loop inside your every(.. loop its iterating twices i.e : if every.. loop is getting first row then .each loop is iterating through whole table(every tr in row) that's why only last value is shown inside div.

    But , here there is no need to use each loop because you can get that name value by using this.data() it will return you JSON Object with all data from your row .So, just use .name to get name value and then add that value to the generated div using .innerHTML.

    Demo code :

    /* Formatting function for row details - modify as you need */
    function format(d) {
      // `d` is the original data object for the row
      return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
        '<tr>' +
        '<td>Full name:</td>' +
        '<td>' + d.name + '</td>' +
        '</tr>' +
        '<tr>' +
        '<td>Extension number:</td>' +
        '<td>' + d.extn + '</td>' +
        '</tr>' +
        '<tr>' +
        '<td>Extra info:</td>' +
        '<td>And any further details here (images etc)...</td>' +
        '</tr>' +
        '</table>';
    }
    
    $(document).ready(function() {
      var table = $('#example').DataTable({
        'ajax': 'https://gyrocode.github.io/files/jquery-datatables/objects.json',
        'columns': [{
            'className': 'details-control',
            'orderable': false,
            'data': null,
            'defaultContent': ''
          },
          {
            'data': 'name'
          },
          {
            'data': 'position'
          },
          {
            'data': 'office'
          },
          {
            'data': 'salary'
          }
        ],
        'order': [
          [1, 'asc']
        ]
      });
    
      // Add event listener for opening and closing details
      $('#example tbody').on('click', 'td.details-control', function() {
        var tr = $(this).closest('tr');
        var row = table.row(tr);
    
        if (row.child.isShown()) {
          // This row is already open - close it
          row.child.hide();
          tr.removeClass('shown');
        } else {
          // Open this row
          row.child(format(row.data())).show();
          tr.addClass('shown');
        }
      });
    
      // Handle click on "Expand All" button
      // Handle click on "Expand All" button
      $('#btn-show-all-children').on('click', function() {
        let containers, user_name;
        var count = 0;
        table.rows().every(function() {
        //get data from row this will return values in json object..
          var d = this.data();
          if (!this.child.isShown()) {
            containers = document.createElement('div');
            containers.setAttribute('id', `container_${d.name.replace(' ', '_')}`);
            containers.innerHTML = d.name;//add value in inside div crated
            this.child(containers).show();
            $(this.node()).addClass('shown'); 
          }
        });
      });
    
      // Handle click on "Collapse All" button
      $('#btn-hide-all-children').on('click', function() {
        // Enumerate all rows
        table.rows().every(function() {
          // If row has details expanded
          if (this.child.isShown()) {
            // Collapse row details
            this.child.hide();
            $(this.node()).removeClass('shown');
          }
        });
      });
    });
    td.details-control {
      background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_open.png') no-repeat center center;
      cursor: pointer;
    }
    
    tr.shown td.details-control {
      background: url('https://cdn.rawgit.com/DataTables/DataTables/6c7ada53ebc228ea9bc28b1b216e793b1825d188/examples/resources/details_close.png') no-repeat center center;
    }
    <link rel='stylesheet' type='text/css' href='https://cdn.datatables.net/1.10.22/css/jquery.dataTables.min.css'>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
    <script src="https://cdn.datatables.net/1.10.22/js/jquery.dataTables.min.js"></script>
    
    <button id="btn-show-all-children" type="button">Expand All</button>
    <button id="btn-hide-all-children" type="button">Collapse All</button>
    <hr>
    <table id="example" class="display" cellspacing="0" width="100%">
      <thead>
        <tr>
          <th></th>
          <th>Name</th>
          <th>Position</th>
          <th>Office</th>
          <th>Salary</th>
        </tr>
      </thead>
      <tfoot>
        <tr>
          <th></th>
          <th>Name</th>
          <th>Position</th>
          <th>Office</th>
          <th>Salary</th>
        </tr>
      </tfoot>
    </table>