AngularJS - how to override directive ngClick
Solution 1
You can't override AngularJS built-in directives. However, you can define multiple directives with the same name and have them executed against the same element. By assigning appropriate priority
to your directive, you can then control whether your directive runs before or after a built-in directive.
This plunker shows how to build an ng-click
directive that executes before the built-in ng-click
does. The code is also shown below. When clicking the link, the custom ng-click
will run first, then the built-in ng-click
does.
index.html
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="[email protected]" data-semver="1.9.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.js"></script>
<script data-require="[email protected]" data-semver="1.0.7" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.js"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MyCtrl">
<a ng-click="alert()">Click me</a>
</body>
</html>
script.js
angular.module('app', [])
.directive('ngClick', function($rootScope) {
return {
restrict: 'A',
priority: 100, // give it higher priority than built-in ng-click
link: function(scope, element, attr) {
element.bind('click', function() {
// do something with $rootScope here, as your question asks for that
alert('overridden');
})
}
}
})
.controller('MyCtrl', function($scope) {
$scope.alert = function() {
alert('built-in!')
}
})
Solution 2
Every directive is a special service inside AngularJS, you can override or modify any service in AngularJS, including directive
For example remove built-in ngClick
angular.module('yourmodule',[]).config(function($provide){
$provide.decorator('ngClickDirective', ['$delegate', function($delegate) {
//$delegate is array of all ng-click directive
//in this case first one is angular buildin ng-click
//so we remove it.
$delegate.shift();
return $delegate;
}]);
});
angular support multiple directives to the same name so you can register you own ngClick
Directive
angular.module('yourmodule',[]).directive('ngClick',function (){
return {
restrict : 'A',
replace : false,
link : function(scope,el,attrs){
el.bind('click',function(e){
alert('do you feeling lucky');
});
}
}
});
check out http://plnkr.co/edit/U2nlcA?p=preview
I wrote a sample that removed angular built-in ng-click
and add a customized ngClick
Related videos on Youtube
Simcha
Updated on July 09, 2022Comments
-
Simcha almost 2 years
I want to override directive ng-click: to some make some $rootscope changes before each execution of ng-click. How to do it?
-
Simcha almost 11 yearsThanks a lot for detailed response)
-
Morteza over 10 yearsBuu, can we stop first ng-click totally? i mean after running 'overridden' alert, 'built-in' not to run.
-
Buu over 10 yearsDon't pass an expression to ng-click, see plnkr.co/edit/uROkIcGKLspLnVsjmAKn?p=preview. If you have to pass s/t, then don't handle it, e.g. $scope.alert = function() {}.
-
Jonathan Palumbo over 9 yearsThis was immensely helpful to me! Thanks.
-
JackNova over 9 yearsthis is not the correct answer, checkout the Eric Chen one below!
-
mr_than about 9 yearsConcur with JackNova, this answer is not correct. * you CAN override/replace all directives as @eric-chen shows below * this example approach will run into issues - you cannot have multiple directives on the same element requesting an isolate scope or setting a template. Eric's approach solves that too
-
Alex White almost 9 yearsHow would you keep both delegates but let the first handler conditionally propagate to the built-in delegate?
-
saiyancoder almost 9 years@AlexWhite my guess is that it's impossible since the
click
binding is being done withelement.bind
inside another function callback already: github.com/angular/angular.js/blob/master/src/ng/directive/… -
meticoeus over 8 years@AlexWhite the simple solution is to simulate this behavior by making a copy of the ngClick event handler and $parse usage in your directive and calling it conditionally from your event handler.