1

I've an angular datatable with nested data and I'm trying to create another datatable on row click function.. rowCallBack function of parent datatable.

This is my outer datatable html;

<table id="tblEmailsByCase" datatable="" dt-options="dtCaseOptions" dt-columns="dtCaseColumns" dt-instance="dtCaseInstance" class="display table table-striped table-bordered table-hover">
    <!-- THIS TABLE IS GENERATED DYNAMICALLY -->
</table>

here is how I'm generating datatable;

    // adding btn column to list

    if($scope.lstEmailsByCases[i].users != null && $scope.lstEmailsByCases[i].users.length > 0 )
    {
        $scope.lstEmailsByCases[i].btn = '<button id="' + 'btn' + i + '">+</button>';
    }

// creating table's column..

    $scope.dtCaseInstance = {};
    $scope.dtCaseOptions = DTOptionsBuilder.fromSource($scope.lstEmailsByCases)
        .withOption('data', $scope.lstEmailsByCases) //pass data source here
        .withOption('dataSrc', '')
        .withOption('rowCallback', rowCallbackCases)
        .withOption('createdRow', createdRowCases)

    //define columns
    $scope.dtCaseColumns = [
        DTColumnBuilder.newColumn('btn').withTitle(''), //this is to show the '+' button
        DTColumnBuilder.newColumn('caseId').withTitle('Case Id'),


    ];

//CALLED WHEN ROW IS CREATED
function createdRowCases(row, data, dataIndex) {
    // Recompiling so we can bind Angular directive
    $compile(angular.element(row).contents())($scope);
}

//HERE IT IS CALLED WHENEVER ROW IS CLICKED
function rowCallbackCases(tabRow, data, dataIndex) {
    if(tabRow.cells[0].firstChild != null)
        {
            $(tabRow).unbind('click');
            $(tabRow).on('click', function() {

                $(this).find('.a1-icon').toggleClass('fa-rotate-180');
                var tr = $(tabRow);
                var table = $scope.dtCaseInstance.DataTable;
                var row = table.row(tr);

                if (row.child.isShown()) {
                    // This row is already open - close it
                    row.child.hide();
                    tr.removeClass('shown');
                    tabRow.cells[0].firstChild.innerHTML = "+"; //change button value to +
                } else if (typeof row.child(formatCaseUsersTable(row.data())) != "undefined") {
                    // Open this row
                    row.child(formatCaseUsersTable(row.data())).show();
                    tr.addClass('shown');
                    tabRow.cells[0].firstChild.innerHTML = "-"; //change button value to -
                }

            });
        }
}

Its working perfectly fine and generating datatable like this;

enter image description here

Now I'm trying to generate another datatable on + button click.. so this is what I'm doing in formatCaseUsersTable function that is calling from rowCallBack function of this datatable.. here is that function;

//CALLED TO CREATE SUB GRID
function formatCaseUsersTable(d) {

    //if detail does not exist
    if (typeof d.users == "undefined") return;

    //defining table
    var html2 = '<table id="tblCaseUsers" datatable="" dt-options="dtCaseUsersOptions" dt-columns="dtCaseUsersColumns" dt-instance="dtCaseUsersInstance" class="display table table-striped table-bordered table-hover">';

    $scope.dtCaseUsersInstance = {};
    $scope.dtCaseUsersOptions = DTOptionsBuilder.fromSource(d.users)
        .withOption('data', d.users) //pass data source here
        .withOption('dataSrc', '')
        .withOption('rowCallback', rowCallbackCaseUsers)
        .withOption('createdRow', createdRowCaseUsers)

    //define columns
    $scope.dtCaseUsersColumns = [
        DTColumnBuilder.newColumn('btn').withTitle(''), //this is to show the '+' button
        DTColumnBuilder.newColumn('userId').withTitle('User Id'),
        DTColumnBuilder.newColumn('userName').withTitle('User Name'),


    ];

  //add button in each row.. this button will be used to show user that the row is expandable
    for (i = 0; i < d.users.length; i++) {
        if(d.users[i].emailsDetail != null && d.users[i].emailsDetail.length > 0 )
        {
            d.users[i].btn = '<button id="' + 'btn' + i + '">+</button>';
        }
    }

    return html2;
}

but it is not working accordingly.. this is html created on + button click..

enter image description here

when I check generated html, table definition is there like this;

enter image description here

But it does not show in grid and doesn't have any columns detail.

Anyone have idea what I'm missing??

5
  • 2
    I don't like the idea of mixing AngularJS together with jQuery here in your example, but still it looks like you are simply returning html2 string in your formatCaseUsersTable method without compiling it, so angularjs could attach datatable directive to it. Can you try returning something like return $compile(angular.element(html2))($scope); and see if it helps? Commented Jan 15, 2018 at 15:36
  • Have you tried the proposed solution? Commented Jan 17, 2018 at 10:45
  • @StanislavKvitash sorry for late response... was a little bit busy.. Commented Jan 19, 2018 at 9:01
  • O Man... this did magic.. return $compile(angular.element(html2))($scope); Thank you..make it answer so I can mark it... Commented Jan 19, 2018 at 9:02
  • 1
    Great it helped you, added as answer :) Commented Jan 19, 2018 at 14:11

1 Answer 1

2
+50

As we can see from your code - formatCaseUsersTable method simply returns html2 as a string, without compiling it, so AngularJS could attach datatable directive to the table element. You have to use $compile service to compile the string into template, so this should work in your case:

function formatCaseUsersTable(d) {
    //..

    //defining table
    var html2 = '<table id="tblCaseUsers" datatable="" dt-options="dtCaseUsersOptions" dt-columns="dtCaseUsersColumns" dt-instance="dtCaseUsersInstance" class="display table table-striped table-bordered table-hover">';
    //....

    return $compile(angular.element(html2))($scope);
} 
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.