How to create jQuery Datatable Drill-down rows?

后端 未结 3 1041
傲寒
傲寒 2020-12-01 20:35

In my MVC project, I am trying to use a single Datatable and collapse the rows for detail data as shown on Creating an expandable master-details table (jQuery D

相关标签:
3条回答
  • 2020-12-01 21:07

    There is a good example on Datatables Blog having also a wonderful sliding property. There is unfortunately not so much example on the web regarding to this issue, but I hope this example is useful for you.

    0 讨论(0)
  • 2020-12-01 21:11

    I know this is an old thread. But I could not find any good examples since then. I created a working example which is fully scalable using jQuery (3.5.0) and Datatables (1.10.19). Table, columns, rows and sub tables are created on the fly based on data structure.

    You can find the demo and code here - https://banglaonline.org/dashboard/temp/dt.html. The js code is in https://banglaonline.org/dashboard/temp/dt.js.

    function dataStructure() - creates the first table

    function dataStructure(){
        $("#content_structure").html("<div id='content_structure_table' style='width:80%'></div>");
        var groupBy=[fieldOrder[0].field];//level 1 order
        var dtTextColumnIndex=[];
        var dtNumColumnIndex=[];
        var colCount=1;
        var valuefunction=null;//dataCreateValueFunctions();
    
        tblFormatParam = formatTblDataStructure('tblDataStructure',0,"1=1");
        html = tblFormatParam[0];
        tableDef = tblFormatParam[1];
    
        $("#content_structure_table").html(html);   
        var table = $('#tblDataStructure').DataTable(tableDef);
        //drill down event
        $('#tblDataStructure tbody').on('click', 'td.details-control', function(){
            e=$(this);
            drillTblDataStructure(e,table,valuefunction);
        });
    
        $('#tblDataStructure' ).bind( 'xhr.dt', function () {
            var json = table.ajax.json();
            $('#tblDataStructure').unbind( 'xhr.dt');
            //structureChart(json.data);
        });
    
    }
    
    

    function drillTblDataStructure - controls the expansion and contraction of nested tables

    
    function drillTblDataStructure(td,table,valuefunction) {
        //console.log("td clicked -"+td.attr("datavalue"));
        var tr = td.closest('tr');
        var row = table.row( tr );   
        currentFieldOrder = parseInt(td.attr("fieldorder"));
        //close all other open rows
        tdDrillControls = document.querySelectorAll("td.details-control");
        for (var i=0;i<tdDrillControls.length;i++){
            tdi= $(tdDrillControls[i]);
            tri = tdi.closest("tr");
            r = table.row( tri);
            if (r.child.isShown() && (tdi.attr("datavalue") != td.attr("datavalue"))) {//second condition is importatnt, otherwise the row will be keep on showing
    
                r.child.hide();
                tri.removeClass('shown');
                tdi.html('<span class="ui-icon ui-icon-plus"></span>')
            }
        }
        if (row.child.isShown()) {
            // This row is already open - close it
            row.child.hide();
            tr.removeClass('shown');
            td.html('<span class="ui-icon ui-icon-plus"></span>')
        }
        else {
            td.html('<span class="ui-icon ui-icon-minus"></span>')  
            childFieldOrder = currentFieldOrder +1;
            var whereClause = td.attr("whereClause")+" and "+td.attr("datacolumn")+" = '"+td.attr("datavalue")+"'"; 
            var childTableID = childFieldOrder*10+iTableCounter;
            tblFormatParam = formatTblDataStructure('tblDataStructure_' + childTableID,childFieldOrder,whereClause);
            html = tblFormatParam[0];
            tableDef = tblFormatParam[1];
            // Open this row
            row.child( html ).show();
            tr.addClass('shown');
            var oInnerTable = $('#tblDataStructure_' + childTableID).DataTable(tableDef);
            $('#tblDataStructure_' + childTableID).bind( 'xhr.dt', function () {//table data is loaded via ajax
                var json = oInnerTable.ajax.json();
                $('#tblDataStructure_' + childTableID).unbind( 'xhr.dt');                                   
            });
            $('#tblDataStructure_' + childTableID +' tbody').on('click', 'td.details-control', function(){
                e=$(this);
                drillTblDataStructure(e,oInnerTable,valuefunction);
            });
            iTableCounter++;
        }
    }
    
    

    function formatTblDataStructure - used by the above two functions to create table structure and definition for Datatables

    function formatTblDataStructure ( table_id, groupOrder, whereClause) {
        var dtTextColumnIndex=[];
        var dtNumColumnIndex=[];
        var colCount=1;
        if(groupOrder<fieldOrder.length-1) //it is not the last item in the order
            var tdColumns=[
                {   className:      'details-control',
                    orderable:      false,
                    data:           null,
                    defaultContent: '<span class="ui-icon ui-icon-plus style="cursor:pointer;"></span>'
                }
            ];
        else
            var tdColumns=[
                {   className:      '',
                    orderable:      false,
                    data:           null,
                    defaultContent: ''
                }
            ];
        tdColumns.push({data:fieldOrder[groupOrder].field});
        html="<table id='"+table_id+"' ><thead><tr><th></th>";
        thtml="<tr><td></td>";
    
        html+="<th>"+fieldOrder[groupOrder]["dataField"]+"</th>";
        thtml+="<td></td>"
        dtTextColumnIndex.push(colCount);
        colCount++;
        var valuefunction=[];
    
        for(f in valueFields){//getting field names from json column names
            html+="<th>"+valueFields[f]["dataField"]+"</th>";
            thtml+="<td></td>"
            dtNumColumnIndex.push(colCount);
            colCount++;
            txt = valueFields[f].groupFunction+"("+valueFields[f].field+") as `"+valueFields[f].field+"`";
            valuefunction.push(txt);
            tdColumns.push({data:valueFields[f].field});
        }
        html+="</tr></thead><tbody>"+thtml+"</tr></tbody></table>"; 
        groupBy=[fieldOrder[groupOrder].field]; 
        var tableDef={
            "ajax":{
                url: src,
                data:{
                    request:'dataStructure'
                    ,dbid:sessionID
                    ,group:JSON.stringify(groupBy)
                    ,where:whereClause
                    ,value:JSON.stringify(valuefunction)
                    ,dt:"assoc"
                }
            },
            createdRow: function( row, data, dataIndex ) {
                $( row ).find('td:eq(0)').attr(
                    {
                        'fieldOrder': groupOrder,
                        'datavalue': data[fieldOrder[groupOrder].field],
                        'datacolumn': fieldOrder[groupOrder].field,
                        'whereClause': whereClause
                    }
                );
            },
            columns: tdColumns,
            columnDefs: [
            {
                targets: dtTextColumnIndex,
                className: 'dt-body-left dt-head-left'
            },
            {
                targets: dtNumColumnIndex,
                className: 'dt-body-right dt-head-right'
                //,"render": function ( data, type, row, meta ) {
                //  return infGroup.format(data);
                //}
            }
          ]
        }
        return [html,tableDef];
    }
    

    In the example, data is retrieved as json via ajax from a php backend. Example json response:

    {
    
    "data": [
    
    { "dash_uploaded_data_text1": "Dept 1", "dash_uploaded_data_numeric1": "3", "dash_uploaded_data_numeric2": "11" },
    
    { "dash_uploaded_data_text1": "Dept 4", "dash_uploaded_data_numeric1": "4", "dash_uploaded_data_numeric2": "8" }
    
    ]
    
    }
    
    0 讨论(0)
  • 2020-12-01 21:24

    I did similar work for one of the projects. I had one collapse/expand button that works for the whole table and each row has its one collapse expand icon. here is my code.

    Note: I have renamed the variables to hide my data so the code might not work as it is.

    function populateInstanceTable(tableData){
        // Use to determine whether the child rows for all parents should be shown or hidden.
        var SHOW_ALL_CHILDREN_FLAG = false;
        var CHILD_DISPLAY_STATE_OVERRIDE = false;
        var TABLE = $('#table_instance').DataTable(
                                                    {
                                                        'aaData': tableData,
                                                        'bProcessing': true,
                                                        'aoColumns': [
                                                                        {
                                                                            'sTitle': 'Column1',
                                                                            'mData' : 'col1Data'
                                                                        }, 
                                                                        {
                                                                            'sTitle': 'Column2',
                                                                            'mData' : 'col2Data'
                                                                        },
                                                                        {
                                                                            'sTitle': 'Column3',
                                                                            'mData': 'col3Data'
                                                                        },
                                                                        {
                                                                            'class': 'show-details',
                                                                            'orderable': false,
                                                                            'data': null,
                                                                            'defaultContent': ''
                                                                        }
                                                                    ]
                                                    }
                                                );
        function getDetailContent(details) {
            return '<table cellpadding="5" cellspacing="0" border="0" style="padding-left:50px;">' +
                   '<tr>' +
                        '<td style="border:0px;">More Details:</td>'+
                        '<td style="text-align:left;max-width:100%;border:0px;">' + details + '</td>' +
                   '</tr>' +
                   '</table>';
        }
    
        //This function shows and hides multiple child rows with details, for following conditions
        // when user clicks '+' or '-' icon
        // When user uses search
        // when user changes the number of entries per page
        // when user navigates through the table
        // @remark: With exception of expand all and collapse all events, the display state is retained for child rows 
        //that have been previously visited. Visited implies the parent row's show or hide details icon was individually clicked.
        function collapseOrExpandRows() {
            var numberOfVisibleParentRows = $('#table_instance tbody tr td.show-details').length;
            for (var i = 0; i < numberOfVisibleParentRows; i++) {            
            var parentJQRow = $('.show-details').parents('tr').eq(i);
                var parentDTRow = TABLE.row(parentJQRow);
                // visited_child helps us retain the state of the child row display while 
                // searching, navigating, sorting or changing number of entries
                // We always change the state of child if collapse all(- icon) or expand all(+ icon) is clicked.
                if (parentJQRow.hasClass('visited_child') === false  || CHILD_DISPLAY_STATE_OVERRIDE === true) {
                    if (SHOW_ALL_CHILDREN_FLAG === true) {
    
                        // We are populating a child row with a table because the parent datatable does not support colspan property.
                        parentDTRow.child(getDetailContent(parentDTRow.data().details)).show();
                        parentJQRow.addClass('shown');
                    } 
                    else {
                        parentDTRow.child.hide();
                        parentJQRow.removeClass('shown');
                    }
                }
            }
        }
    
        //To display details, this event handler shows or hides a single child row 
        //when the show-details cell is clicked on the parent row
        $('#table_instance tbody').on('click', 'td.show-details', function() {
            var parentJQRow = $(this).parents('tr'); 
            var parentDTRow = TABLE.row(parentJQRow);
    
            //visited_child helps us retain the state of the child row display while 
            // searching, navigating, sorting or changing number of entries
            parentJQRow.addClass('visited_child');
    
            if (parentDTRow.child.isShown()) {
                parentDTRow.child.hide();
                parentJQRow.removeClass('shown');
            } 
            else {
                parentDTRow.child(getDetailContent(parentDTRow.data().details)).show();
                parentJQRow.addClass('shown');
            }
    
            CHILD_DISPLAY_STATE_OVERRIDE = false;
        });
    
        // This event handler retains the state of the child row display 
        // when navigating through the table.
        $('.dataTables_paginate').on('click', function() {
            collapseOrExpandRows();
        });
    
        // This event handler hides child row for all visible parents.
        $('.collapseall').on('click', function() {
            CHILD_DISPLAY_STATE_OVERRIDE = true;
            SHOW_ALL_CHILDREN_FLAG = false;
            collapseOrExpandRows();
        });
    
        // This event handler shows child row of all visible parents. 
        $('.expandall').on('click', function() {
            CHILD_DISPLAY_STATE_OVERRIDE = true;
            SHOW_ALL_CHILDREN_FLAG = true;
            collapseOrExpandRows();
        });
    
        // This event handler retains the state of the child row display 
        // when the user selects the number of entries to display in the table
        $('div.dataTables_length select').on('change', function() {
            collapseOrExpandRows();
        });
    
        // This event handler retains the state of the child row display 
        // when the user clicks on header to sort
        $('thead > tr > th', '#table_instance').click(function() {
            if ($(this).hasClass('show-details') === false) {
                collapseOrExpandRows();
            }
        });
    
        // This event handler retains the state of the child row display 
        // when the user searches
        $('div.dataTables_filter input').keyup(function() {
            collapseOrExpandRows();
        });
    }
    

    I have attached the screenshot for your help.

    0 讨论(0)
提交回复
热议问题