Angular Directive ng-click Not Working
Solution 1
In order to make ng-click
directive work it needs to be processed('compiled') by angular infrastructure first, so instead of manually creating li
elements in your directive about which angular doesn't have a clue they exist, you can use ng-repeat
in directive template as follows (no need for manually creating DOM elements):
angular.module('app.directives', [])
.directive('process', function() {
return {
restrict: 'E'
, replace: true
, template: '<ol class="nav nav-pills"><li ng-class="{active: stage==at}" ng-click="stage.select()" ng-repeat="stage in stages"><a>{{stage.label}}</a></li></ol>'
, scope: {
stages: "="
, at: "="
}
}
});
Modified plunker: http://plnkr.co/edit/SW1Ph0nIjVYW3UzixtBx?p=preview
I think it's most elegant solution. Of course you can move template to eternal file and reference it via templateUrl
.
Alternatively you could use $compile
service on element after you added li
items manually but it feels like a hack.
Solution 2
Working url http://plnkr.co/edit/3zuDuQDjhA5UY5nLD09Z?p=preview
Please make below change in url directive
angular.module('app.directives', [])
.directive('process', function($compile) {
return {
restrict: 'E'
, replace: true
, template: '<ol class="nav nav-pills"></ol>'
, scope: {
stages: "="
, at: "="
}
, link: function postLink(scope, element, attrs) {
for (var i = 0; i < scope.stages.length; i++) {
var $stage = $('<li ng-click="stages['+i+'].select()"><a>'+scope.stages[i].label+'</a></li>');
if (scope.at == scope.stages[i]) {
$stage.addClass('active');
}
$(element).append($stage);
$compile($(element))(scope);
}
}
}
});
i have injected $complie and added one line $compile($(element))(scope);
jtfairbank
Updated on June 08, 2022Comments
-
jtfairbank about 2 years
I have an external controller that contains a directive inside of its view. The directive gets a list of process points and generates links where you can select each one. It correctly sets up the HTML in the link function, but the links' ng-click actions don't work.
Any ideas? :)
Code for the Non-Plunkering
HTML
<!DOCTYPE html> <html> <head><link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.2/css/bootstrap-combined.min.css" rel="stylesheet"> <script src="http://code.jquery.com/jquery-2.0.3.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script> <script src="script.js"></script> </head> <body ng-app="app"> <div ng-controller="widget"> <process stages="production" at="productionAt"></process> </div> </body> </html>
JS
angular.module('app', ['app.directives', 'app.controllers']); angular.module('app.controllers', []) .controller('widget', function($scope) { var selectStage = function () { alert(this.label + " selected."); $scope.processAt = this; } $scope.production = [ {label: "Starting", select: selectStage} , {label: "Fermenting", select: selectStage} , {label: "Pouring", select: selectStage} , {label: "Beer!", select: selectStage} ]; $scope.productionAt = $scope.production[0]; }); angular.module('app.directives', []) .directive('process', function() { return { restrict: 'E' , replace: true , template: '<ol class="nav nav-pills"></ol>' , scope: { stages: "=" , at: "=" } , link: function postLink(scope, element, attrs) { for (var i = 0; i < scope.stages.length; i++) { var $stage = $('<li ng-click="stages['+i+'].select()"><a>'+scope.stages[i].label+'</a></li>'); if (scope.at == scope.stages[i]) { $stage.addClass('active'); } $(element).append($stage); } } } });