Reputation: 350
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("");
};
}]);
Upvotes: 4
Views: 8181
Reputation: 1409
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)
Upvotes: 4