<meta name="description" content="DataTable with four levels of child-row detail using Nested Tables" />
    <!-- Bootstrap CSS CDN -->
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/css/bootstrap.min.css" integrity="sha384-9gVQ4dYFwwWSjIDZnLEWnxCjeSWFphJiwGPXr1jddIhOegiu1FwO5qRGvFXOdJZ4" crossorigin="anonymous">
    <!-- DataTables Custom CSS -->
    <link rel="stylesheet" href="https://cdn.datatables.net/1.10.19/css/jquery.dataTables.min.css" />
    <link rel="stylesheet" href="https://cdn.datatables.net/responsive/2.2.3/css/responsive.dataTables.min.css" />
    <link rel="stylesheet" href="https://cdn.datatables.net/buttons/1.5.4/css/buttons.dataTables.min.css" />
<div class="row row-padding">
    <div class="col-12">
        <div class="card">
            <div class="card-body">
                <table id="example" class="display compact nowrap w-100">
                    <thead>
                        <tr>
                            <th></th>
                            <th>Client | Matter | Invoice</th>
                            <th style="width:69px">WIP</th>
                            <th style="width:69px">AR</th>
                            <th style="width:69px">0-30</th>
                            <th style="width:69px">31-60</th>
                            <th style="width:69px">61-90</th>
                            <th style="width:69px">91-120</th>
                            <th style="width:69px">121+</th>
                            <th style="width:69px">Susp</th>
                        </tr>
                    </thead>
                </table>
            </div>
        </div>
    </div>
</div>
    <!-- jQuery CDN -->
    <script src="https://code.jquery.com/jquery-3.3.1.min.js"
            integrity="sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8="
            crossorigin="anonymous"></script>
    <!-- Bootstrap JS -->
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.1.0/js/bootstrap.min.js" integrity="sha384-uefMccjFJAIv6A+rW+L4AHf99KvxDjWSu1z9VI8SKNVmz4sk7buKt/6v9KI65qnm" crossorigin="anonymous"></script>
    <!-- DataTables CDN -->
    <script src="https://cdn.datatables.net/1.10.19/js/jquery.dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/responsive/2.2.3/js/dataTables.responsive.min.js"></script>
 
@import "https://fonts.googleapis.com/css?family=Muli:300,400,500,600,700";
    table.display {
        font-family: 'Muli'
    }
    table.dataTable.compact tbody th, table.dataTable.compact tbody td, table.dataTable.compact tfoot td {
      /*padding: 0px 17px 0px 4px;*/
        padding: 0px 0px 0px 0px;
    }
    td.details-control {
        background: url(https://www.datatables.net/examples/resources/details_open.png) no-repeat center center;
        cursor: pointer;
        width: 30px;
        transition: .5s;
    }
    tr.shown td.details-control {
        background: url(https://www.datatables.net/examples/resources/details_close.png) no-repeat center center;
        width: 30px;
        transition: .5s;
    }
    td.details-control1 {
        background: url(https://www.datatables.net/examples/resources/details_open.png) no-repeat center center;
        cursor: pointer;
        width: 40px;
        transition: .5s;
    }
    tr.shown td.details-control1 {
        background: url(https://www.datatables.net/examples/resources/details_close.png) no-repeat center center;
        width: 40px;
        transition: .5s;
    }
    td.details-control2 {
        background: url(https://www.datatables.net/examples/resources/details_open.png) no-repeat center center;
        cursor: pointer;
        width: 50px;
        transition: .5s;
    }
    tr.shown td.details-control2 {
        background: url(https://www.datatables.net/examples/resources/details_close.png) no-repeat center center;
        width: 50px;
        transition: .5s;
    }
    .fee-col {
        text-align: right;
    }
    .label-col {
        text-align: left;
    }
    tr.shown td {
        background-color: lightgrey !important;
        transition: .5s;
        font-weight: 800
    }
    td.invoice-date {
        background-color: rgba(237, 205, 255, .2);
    }
    td.invoice-author {
        background-color: rgba(237, 205, 255, .2);
    }
    td.invoice-notes {
        background-color: rgba(237, 205, 255, .2);
    }
 
        var childEditors = {};  // Globally track created chid editors
        var childTable;
        var childTable2;
        $(document).ready(function () {
            // Return table with id generated from row's name field
            function format(rowData) {
                var childTable = '<table id="cl' + rowData.clientID + '" class="display compact nowrap w-100" width="100%">' +
                    '<thead style="display:none"></thead >' +
                    '</table>';
                return $(childTable).toArray();
            }
            function format2(rowData) {
                var childTable = '<table id="mt' + rowData.matterID + '" class="display compact nowrap w-100" width="100%">' +
                    '<thead style="display:none"></thead >' +
                    '</table>';
                return $(childTable).toArray();
            }
            function format3(rowData) {
                var childTable = '<table id="in' + rowData.invoice + '" class="display wrap w-100 cell-border" width="100%">' +
                    '<thead style="display:none"></thead >' +
                    '</table>';
                return $(childTable).toArray();
            }
            // Main table
            var table = $('#example').DataTable({
                dom: 't',
                ajax: {
                    url: 'https://output.jsbin.com/zisabof.json',
                    dataSrc: 'data'
                },
                pageLength: 20,
                columns: [
                    {
                        className: 'details-control',
                        orderable: false,
                        data: null,
                        defaultContent: ''
                    },
                    {
                        data: "clientName",
                        "render": function (data, type, row) {
                            data = '<a href="/client/detail/' + row.clientID + '?name=' + row.clientName + '">' + data + '</a>';
                            return data;
                        }
                    },
                    { data: "wip" },
                    { data: "ar" },
                    { data: "ar0_30" },
                    { data: "ar31_60" },
                    { data: "ar61_90" },
                    { data: "ar91_120" },
                    { data: "ar121_" },
                    { data: "suspense" }
                ],
                columnDefs: [
                    {
                        targets: [2, 3, 4, 5, 6, 7, 8, 9],
                        className: "fee-col"
                    },
                    {
                        targets: [1],
                        className: "label-col"
                    }
                ],
                order: [[1, 'asc']],
            });
            // Add event listener for opening and closing first level childdetails
            $('#example tbody').on('click', 'td.details-control', function () {
                var tr = $(this).closest('tr');
                var row = table.row(tr);
                var rowData = row.data();
 
                if (row.child.isShown()) {
                    // This row is already open - close it
                    row.child.hide();
                    tr.removeClass('shown');
                    // Destroy the Child Datatable
                    $('#cl' + rowData.clientID).DataTable().destroy();
                }
                else {
                    // Open this row
                    row.child(format(rowData)).show();
                    var id = rowData.clientID;
                    childTable = $('#cl' + id).DataTable({
                        dom: "t",
                        ajax: {
                            url: 'https://output.jsbin.com/dutelom.json',
                            dataSrc: 'data'
                        },
                        columns: [
                            {
                                className: 'details-control1',
                                orderable: false,
                                data: null,
                                defaultContent: ''
                            },
                            {
                                data: "matterName",
                                render: function (data, type, row) {
                                    data = '<a href="/client/detail/' + row.matterID.substring(1, 6) + '?name=[Client Name]">' + data + '</a>';
                                    return data;
                                }
                            },
                            { data: "wip" },
                            { data: "ar" },
                            { data: "ar0_30" },
                            { data: "ar31_60" },
                            { data: "ar61_90" },
                            { data: "ar91_120" },
                            { data: "ar121_" },
                            { data: "suspense" }
                        ],
                        columnDefs: [
                            {
                                targets: [2, 3, 4, 5, 6, 7, 8, 9],
                                className: "fee-col"
                            },
                            {
                                targets: [1],
                                className: "label-col"
                            }
                        ],
                        select: false,
                    });
                    tr.addClass('shown');
                }
            });
            // Add event listener for opening and closing second level childdetails
            $('tbody').on('click', 'td.details-control1', function () {
                var tr = $(this).closest('tr');
                var row = childTable.row(tr);
                var rowData = row.data();
                if (row.child.isShown()) {
                    // This row is already open - close it
                    row.child.hide();
                    tr.removeClass('shown');
                    // Destroy the Child Datatable
                    $('#mt' + rowData.matterID).DataTable().destroy();
                }
                else {
                    // Open this row
                    row.child(format2(rowData)).show();
                    var id = rowData.matterID;
                    childTable2 = $('#mt' + id).DataTable({
                        dom: "t",
                        ajax: {
                            url: 'https://output.jsbin.com/zohiroz.json',
                            dataSrc: 'data'
                        },
                        columns: [
                            {
                                className: 'details-control2',
                                orderable: false,
                                data: null,
                                defaultContent: ''
                            },
                            {
                                data: "invoice",
                                "render": function (data, type, row) {
                                    data = '<a href="#">' + data + '</a>';
                                    return data;
                                }
                            },
                            { data: "wip" },
                            { data: "ar" },
                            { data: "ar0_30" },
                            { data: "ar31_60" },
                            { data: "ar61_90" },
                            { data: "ar91_120" },
                            { data: "ar121_" },
                            { data: "suspense" }
                        ],
                        columnDefs: [
                            {
                                targets: [2, 3, 4, 5, 6, 7, 8, 9],
                                className: "fee-col"
                            },
                            {
                                targets: [1],
                                className: "label-col"
                            }
                        ],
                        select: false,
                    });
                    tr.addClass('shown');
                }
            });
            // Add event listener for opening and closing third level childdetails
            $('tbody').on('click', 'td.details-control2', function () {
                var tr = $(this).closest('tr');
                var row = childTable2.row(tr);
                var rowData = row.data();
                console.log(rowData.invoice);
                if (row.child.isShown()) {
                    // This row is already open - close it
                    row.child.hide();
                    tr.removeClass('shown');
                    // Destroy the Child Datatable
                    $('#in' + rowData.invoice).DataTable().destroy();
                }
                else {
                    // Open this row
                    row.child(format3(rowData)).show();
                    var id = rowData.invoice;
                    childTable3 = $('#in' + id).DataTable({
                        dom: "t",
                        ajax: {
                            url: 'https://output.jsbin.com/buniye.json',
                            dataSrc: 'data'
                        },
                        columns: [
                            {
                                className: 'details-control3',
                                orderable: false,
                                data: null,
                                defaultContent: ''
                            },
                            { data: "date" },
                            { data: "author" },
                            { data: "note" }
                        ],
                        columnDefs: [
                            {
                                targets: [1],
                                className: "invoice-date pl-5"
                            },
                            {
                                targets: [2],
                                className: "invoice-author px-2"
                            },
                            {
                                targets: [3],
                                className: "invoice-notes px-2"
                            }
                        ],
                        select: false,
                    });
                    tr.addClass('shown');
                }
            });
        });
Output

You can jump to the latest bin by adding /latest to your URL

Dismiss x
public
Bin info
anonymouspro
0viewers