4

I am using jQuery DataTable directive with angularJS which is working fine. The problem I am facing is adding javascript function to "TR" dynamically with "ng-click" which is not working. It seem's like dynamically added elements are not recognized by angular.

Can somebody help me out solving this problem.

Directive :

angular.module('ngdemo.directives', []).directive('myTable', function() {
    return function(scope, element, attrs) {

        // apply DataTable options, use defaults if none specified by user
        var options = {};
        if (attrs.myTable.length > 0) {
            options = scope.$eval(attrs.myTable);
        } else {
            options = {
                "bStateSave": true,
                "iCookieDuration": 2419200, /* 1 month */
                "bJQueryUI": true,
                "bPaginate": false,
                "bLengthChange": false,
                "bFilter": false,
                "bInfo": false,
                "bDestroy": true
            };
        }

        // Tell the dataTables plugin what columns to use
        // We can either derive them from the dom, or use setup from the controller           
        var explicitColumns = [];
        element.find('th').each(function(index, elem) {
            explicitColumns.push($(elem).text());
        });
        if (explicitColumns.length > 0) {
            options["aoColumns"] = explicitColumns;
        } else if (attrs.aoColumns) {
            options["aoColumns"] = scope.$eval(attrs.aoColumns);
        }

        // aoColumnDefs is dataTables way of providing fine control over column config
        if (attrs.aoColumnDefs) {
            options["aoColumnDefs"] = scope.$eval(attrs.aoColumnDefs);
        }

        if (attrs.fnRowCallback) {
            options["fnRowCallback"] = scope.$eval(attrs.fnRowCallback);
        }

        // apply the plugin
        var dataTable = element.dataTable(options);



        // watch for any changes to our data, rebuild the DataTable
        scope.$watch(attrs.aaData, function(value) {
            var val = value || null;
            if (val) {
                dataTable.fnClearTable();
                dataTable.fnAddData(scope.$eval(attrs.aaData));
            }
        });
    };
});

In My Controller:

app.controller('SourceCtrl', ['$scope', 'SharedFactory','$location','$compile', function ($scope, SharedFactory,$location,$compile) {
    $scope.columnDefs = [ 
         { 
             "mDataProp": "desc", 
             "aTargets":[0],
         },
         { "mDataProp": "name", "aTargets":[1] },
         { "mDataProp": "desc", "aTargets":[2] }
    ];

    $scope.overrideOptions = {
             "bServerSide": true,
             "iDisplayLength": 2,
             "sAjaxSource": "ajaxCall",
             "aaSorting": [[ 0, "desc" ]],
             "fnServerData": function ( sSource, aoData, fnCallback,oSettings ) {
                      var startIndex = SharedFactory.fnGetKey(aoData, "iDisplayStart");
                      var length = SharedFactory.fnGetKey(aoData, "iDisplayLength");
                      var sortAttr = 'sourceType';//fnGetKey(aoData,"iSortCol_0");
                      var sortDir = 'DESC';//fnGetKey(aoData,"sSortDir_0");
                      sSource="ajaxCall";
                      $.getJSON(sSource, function (aoData) { 
                          aoData.iTotalRecords = aoData.size;
                          aoData.iTotalDisplayRecords = aoData.size;
                          fnCallback(aoData);
                      });
            },
            "sAjaxDataProp": "aaData",
            "fnCreatedRow": function( nRow, aData, iDataIndex ) {
                $(nRow).attr('ng-click','selectRow()');
             }
     };

    $scope.selectRow = function() {
        alert("");
    };
}]);
1
  • Hi, Is there a working example that Salman or Alexander can point to.. I have the same problem. Thanks Commented Sep 28, 2014 at 0:45

1 Answer 1

4

Well, dynamically created stuff (especially jquery ui) doesn't know anything about angular. That's because angular make compilation of the nodes when processing. So there are few options there:

1) Before adding some dynamic content you can compile it. In this case angular can know about it and all feature like directives, binding etc. can work.

row.push($compile(content)($scope)[0].innerHTML);

In this sample we added compiled content to the row (cell). And the content can have any number of angular directives. But you should carefully pass on the correct scope to have the directives working as you expected.

Another way is just to deal with pure js. In this case you can just declare onclick handlers and inside of them make finding of the necessary scope and call the method on it:

angular.element('item').scope().handleClick(row);

And as the code is called from non-angular part you should wrap it into $scope.$apply:

$scope.handleClick = function(row) {
    $scope.$apply(function() {
        ... place handling logic here
    });
}

But I would better recommend to migrate to angular data grids (like ngGrid)

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks Alex that was really helpful. It actually solved my problem. Is there any problem to use datatable and not ngGrid ?
No special problem with that. I just prefer to use clean angularjs stuff which is more flexible when integrating in your application. If you need you can use datatable (we used it too but then we decided to migrate to an angularjs grid directives). Another alternatives: ng-table, smart-table etc.
Alex, I am using jQuery also with angular JS in my project. Such as toggle the class, hide show the divs. So is it a good approach to use jquery like this with angularJS ?
All of this is supported in AngularJS. So instead of jquery you can use ng-show, ng-hide, ng-class, ng-style etc. But for some time you may still need to handle this manually (for ex. inside of the directives) but they are rare cases.
This doesn't work for me. I'm trying to run a function when clicking on a link in the table. I have content = '<a href="javascript:;" ng-click="doStuff()">stuff</a>' and from the render function for that column I return $compile(content)($scope)[0].outerHTML (innerHTML gives anything under the anchor). doStuff() is defined on the scope but does not get called.

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.