DataTable in subrow... inside another DataTable?

DataTable in subrow... inside another DataTable?

jLinuxjLinux Posts: 981Questions: 73Answers: 75

Im trying to create a table that will be used to view data on sessions, the table has rows with some basic session info, and you can click the ( + ) to view the row details.

I wanted the table inside the row details to also be a DataTable, so the viewer could sort the data, and maybe even hide/show column visibility.

Is it possible to have a DataTable inside a DataTable?

I also wanted to postpone the DataTable initialization of the tables in the child rows, as the data isnt even there until the AJAX request is completed. Heres the JS code thus far:

details: function () {
    "use strict";

    var $sessions_table = $('#my-sessions');

    // Format child rows with session data
    function format ( data ) {
        var table = '<table cellpadding="5" cellspacing="0" border="0" class="session-data width-full">' +
            '<thead>' +
            '<tr>' +
            '<th>Time</th>' +
            '<th>Partition</th>' +
            '<th>URI</th>' +
            '<th>Response</th>' +
            '<th>Req Type</th>' +
            '</thead>' +
            '<tbody>';


        //timestamp, partition_id, http_response, request_type, uri

        $.each(data, function(i,v){
            table += '<tr>' +
            '<td>' + v.timestamp + '</td>' +
            '<td>' + v.partition_id + '</td>' +
            '<td>' + v.uri + '</td>' +
            '<td>' + v.http_response + '</td>' +
            '<td>' + v.request_type + '</td>' +
            '</tr>';
        });

        table += '</tbody></table>';

        return table;
    }

    var $sessions_dt = $sessions_table.DataTable( {
        columns: [
            {
                className:      'details-control',
                orderable:      false,
                data:           null,
                defaultContent: ''
            },
            { data: 'terminate' },
            { data: 'IP' },
            { data: 'date' },
            { data: 'uri' }
        ],
        "order": [[1, 'asc']]
    } );

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

        if ( row.child.isShown() ) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
        }
        else {
            var $this = $( this );
            var $row = $this.closest( 'tr' );
            var session_id = $row.data( 'row-id' );

            row.child( 'Loading...' ).show();

            tr.addClass('shown');
            $.ajax({
                type: 'GET',
                dataType: 'json',
                url: '/REST/account/session_data/session_id/' + session_id,
                success: function (response) {
                    //console.log('Response: ', response);
                    row.child( format(response.result) ).show();
       
                    // Not sure this is right, if it should be here or not
                    $('.session-data').DataTable();
                },
                error: function (xhr, ajaxOptions, thrownError) {
                    var result = jQuery.parseJSON(xhr.responseText);

                    template.alert( 'Error retrieving session ID: ', result.error, 'error', true);
                }
            });
        }
    } );
}

I dont get any error in the console or anything, but the datatable never gets initialized inside the sub row.

Answers

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75
    edited August 2015

    I somewhat got it working now actually. But for some reason, it seems to put two header rows.

    Screenshot: http://d.pr/i/D2XM

    JS Code:

    details: function () {
        "use strict";
    
        var $sessions_table = $('#my-sessions');
    
        // Format child rows with session data
        function format ( data ) {
            var table = '<table cellpadding="5" cellspacing="0" border="0" class="table session-data width-full display compact table-condensed">' +
                '<thead>' +
                '<tr>' +
                '<th>Time</th>' +
                '<th>Partition</th>' +
                '<th>URI</th>' +
                '<th>Response</th>' +
                '<th>Req Type</th>' +
                '</thead>' +
                '<tbody>';
    
    
            //timestamp, partition_id, http_response, request_type, uri
    
            $.each(data, function(i,v){
                table += '<tr>' +
                '<td>' + v.timestamp + '</td>' +
                '<td>' + v.partition_id + '</td>' +
                '<td>' + v.uri + '</td>' +
                '<td>' + v.http_response + '</td>' +
                '<td>' + v.request_type + '</td>' +
                '</tr>';
            });
    
            table += '</tbody></table>';
    
            return table;
        }
    
        var $sessions_dt = $sessions_table.DataTable( {
            columns: [
                {
                    className:      'details-control',
                    orderable:      false,
                    data:           null,
                    defaultContent: ''
                },
                { data: 'terminate' },
                { data: 'IP' },
                { data: 'date' },
                { data: 'uri' }
            ],
            "order": [[1, 'asc']]
        } );
    
        // Add event listener for opening and closing details
        $sessions_table.find('tbody').on('click', 'td.details-control', function () {
            var tr = $(this).closest('tr');
            var row = $sessions_dt.row( tr );
    
            if ( row.child.isShown() ) {
                // This row is already open - close it
                row.child.hide();
                tr.removeClass('shown');
            }
            else {
                var $this = $( this );
                var $row = $this.closest( 'tr' );
                var session_id = $row.data( 'row-id' );
    
                row.child( 'Loading...' ).show();
    
                tr.addClass('shown');
                $.ajax({
                    type: 'GET',
                    dataType: 'json',
                    url: '/REST/account/session_data/session_id/' + session_id,
                    success: function (response) {
                        //console.log('Response: ', response);
                        row.child( format(response.result) ).show();
    
                        $('.session-data' ).DataTable({
                            searching: false,
                            scrollY: 300,
                            paging: false
                        });
                    },
                    error: function (xhr, ajaxOptions, thrownError) {
                        var result = jQuery.parseJSON(xhr.responseText);
    
                        template.alert( 'Error retrieving session ID: ', result.error, 'error', true);
                    }
                });
            }
        } );
    }
    

    PHP/HTML Code:

    <table id="my-sessions" class="table <?php echo TABLE_STYLE_CLASSES; ?>">
        <thead>
        <tr>
            <th>&nbsp;</th>
            <th class="w-100">&nbsp;</th>
            <th>IP Address</th>
            <th>Last Request</th>
            <th>Last URI</th>
        </tr>
        </thead>
        <tbody>
        <?php
        if($sessions)
            foreach($sessions as $s_id => $s):
                echo '<tr data-row-id="' . $s_id . '">';
                if(empty($s)): ?>
                    <td></td>
                    <td class="text-center" class="terminate-session">
                        <a href="#">
                            <i class="fa fa-lg fa-power-off"></i>
                        </a>
                    </td>
                    <td>
                        <?php echo $s_id; ?>
                    </td>
                    <td></td>
                    <td></td>
                <?php
                else:
                    $end = end($s);
                    ?>
                    <td></td>
                    <td class="text-center">
                        <a href="#" class="terminate-session">
                            <i class="fa fa-lg fa-power-off"></i>
                        </a>
                    </td>
                    <td>
                        <?php echo long2ip($end->ip); ?>
                    </td>
                    <td>
                        <?php echo date("F j, Y, g:i a", $end->timestamp); ?>
                    </td>
                    <td>
                        <?php echo $end->uri; ?>
                    </td>
                <?php
                endif;
            endforeach;
        ?>
        </tr>
        </tbody>
    </table>
    
  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    And while im here, one other question... How can I make the scrollY setting only scroll when the table has reached that setting?

    If I have it set to 300 for example, it will fill the space in the child row with nothing, but itll take up space. SS: http://d.pr/i/1d4Mt

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75
    edited August 2015

    I think the space below can be fixed by using scrollCollapse, still wondering whatsup with the double header though.

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    Anyone know what might be causing the header to appear twice?

  • jLinuxjLinux Posts: 981Questions: 73Answers: 75

    I noticed that I forgot the </tr> in my code, so I added it thinking that might be it, but it wasnt. I created some screenshots though...

    Heres a picture of me highlighting the INCORRECT element in the DOM (a DT Div), which highlights the correct header, and pointing out where the real header element is: http://d.pr/i/10qkT

    Then heres where I highlight the CORRECT element in the DOM, (the real header), which highlights the slim little header under the real header in the display: http://d.pr/i/14bfc

    And I know it might not seem like that big of a deal, but heres a picture of what it looks like: http://d.pr/i/154uL

    Just kinda annoying... I know it shouldnt be there

This discussion has been closed.