Andre.Santarosa Andre.Santarosa - 2 months ago 9
AngularJS Question

ng-click dont fire even after call $compile

I'm creating a DataGrid module with some actions, but the ng-click won't fire event after add the $compile statement

MODULE

angular.module('powerGridAngular').service("powerGridContainer", function ($http, powerGridMethods) {

this.buildGrid = function (scope) {
return powerGridMethods.bindData(powerGridMethods.buildHeader(scope.options), scope);
};
});


angular.module('powerGridAngular').service('powerGridMethods', function ($http, $compile) {
this.getJson = function (url) {
console.log(url);
return $http.get(url);
};

this.buildHeader = function (options) {
// create table element
var table = angular.element('<table></table>').addClass('table table-striped');
// create header element
var header = angular.element('<tr></tr>');
// run trough each header field and add them to header
angular.forEach(options[0]['headerFields'], function (val, key) {
header.append(angular.element('<th>' + val + '</th>'));
});
// check if grid has edit, if it have, adds a new blank field header
if (options[0]['hasEdit'] == true)
header.append('<th></th>');

// append header to table
table.append(header);
return table;
}

this.bindData = function (table, scope) {
// get grid options
var options = scope.options;
// get grid data via JSON
var gridData = this.getJson(options[0]['dataUrl']).success(function (data) {
// run rows
angular.forEach(data, function (rowVal, rowKey) {
// create row
var cellRow = angular.element('<tr></tr>');
// run through rows
angular.forEach(rowVal, function (cellVal, cellKey) {
// create through cells
cellRow.append(angular.element('<td></td>').text(cellVal));
});
// check if grid has actions
if (options[0]['hasEdit'] == true) {
// cell that contains icon to open options
cellRow.append(angular.element('<td style="width:30px" ng-click="editRow()"></td>').html('<span class="glyphicon glyphicon-menu-hamburger openMenu" aria-hidden="true"></span>'));
// options menu root
var menuRoot = angular.element('<div></div>').addClass('orgPgOptPanel');
// run through options
angular.forEach(options[0]['actions'], function (val, key) {
// create menu row
var menuItem = angular.element('<div></div>').addClass('orgPgOptPanelMenuItem');
// add menu html
menuItem.append(angular.element(val['menuHtml']));
// append menu item to menu container
menuRoot.append(menuItem);
});
// append menu root
cellRow.append(menuRoot);
}
// append all table cells to table
table.append(cellRow);
});
});
// compile directives
$compile(table.contents())(scope);
// return all table content already compiled
return table;
}

});


CALL

angular.module('pisApp').controller('regionalCtrl', function ($scope, powerGridContainer, $compile) {

$scope.editRow = function () {
console.log('called');
}
$scope.tst = 30;
$scope.editRow();
// header
$scope.header = ['Código', 'Regional']
// get grid data
$scope.gridContainer = angular.element('#gridContainer');
// define options
$scope.options = [{
headerFields: $scope.header,
hasEdit: true,
dataUrl:"../Handlers/Queries/dataGridJsons/getAllRegionals.ashx",
actions: [{
menuHtml: '<button type="button" ng-click="editRow()">Click me!</button>'
},
{
menuHtml:'<span id="spn" class="glyphicon glyphicon-pencil" aria-hidden="true"></span>&nbsp;Editar</a>'
},
{
menuHtml:'<span id="spn" class="glyphicon glyphicon-pencil" aria-hidden="true"></span>&nbsp;Editar</a>'
}
]
}];
// bind grid
$scope.varReturn = powerGridContainer.buildGrid($scope);
var content = angular.element("#gridContainer").append($scope.varReturn);

});

Answer

I think I see the problem. this.getJson is making an asynchronous call, and $compile is being called synchronously - before the table's contents have been appended.

The solution is to make sure you are running $compile on the elements that get appended by the asynchronous callback.

I would probably do it something like:

Change:

// append all table cells to table
table.append(cellRow);

To:

// compile table row
$compile(cellRow)(scope);
// append all table cells to table
table.append(cellRow);

Alternatively, you could just run $compile(table)(scope); at the end of the success callback.

Comments