AngularJS - how to override directive ngClick

28,746

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

Share:
28,746

Related videos on Youtube

Simcha
Author by

Simcha

Updated on July 09, 2022

Comments

  • Simcha
    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
    Simcha almost 11 years
    Thanks a lot for detailed response)
  • Morteza
    Morteza over 10 years
    Buu, can we stop first ng-click totally? i mean after running 'overridden' alert, 'built-in' not to run.
  • Buu
    Buu over 10 years
    Don'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
    Jonathan Palumbo over 9 years
    This was immensely helpful to me! Thanks.
  • JackNova
    JackNova over 9 years
    this is not the correct answer, checkout the Eric Chen one below!
  • mr_than
    mr_than about 9 years
    Concur 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
    Alex White almost 9 years
    How would you keep both delegates but let the first handler conditionally propagate to the built-in delegate?
  • saiyancoder
    saiyancoder almost 9 years
    @AlexWhite my guess is that it's impossible since the click binding is being done with element.bind inside another function callback already: github.com/angular/angular.js/blob/master/src/ng/directive/…
  • meticoeus
    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.