【问题标题】:AngularJS - how to override directive ngClickAngularJS - 如何覆盖指令 ngClick
【发布时间】:2013-08-24 18:23:44
【问题描述】:

我想覆盖指令 ng-click: 在每次执行 ng-click 之前进行一些 $rootscope 更改。怎么做?

【问题讨论】:

    标签: angularjs angularjs-directive angularjs-ng-click


    【解决方案1】:

    每个指令都是AngularJS中的一个特殊服务,你可以覆盖或修改AngularJS中的任何服务,包括指令

    例如移除内置的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支持多个指令同名,所以你可以注册自己的ngClick指令

    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');
          });
        }
      }
    });
    

    查看http://plnkr.co/edit/U2nlcA?p=preview 我写了一个示例,删除了内置的角度 ng-click 并添加了自定义的 ngClick

    【讨论】:

    • 这对我很有帮助!谢谢。
    • 如何保留两个委托,但让第一个处理程序有条件地传播到内置委托?
    • @AlexWhite 我猜这是不可能的,因为 click 绑定已经在另一个函数回调中使用 element.bind 完成:github.com/angular/angular.js/blob/master/src/ng/directive/…
    • @AlexWhite 简单的解决方案是通过在指令中复制 ngClick 事件处理程序和 $parse 用法并从事件处理程序有条件地调用它来模拟这种行为。
    【解决方案2】:

    你不能覆盖 AngularJS 的内置指令。但是,您可以定义多个具有相同名称的指令,并让它们针对同一个元素执行。通过为您的指令分配适当的priority,您可以控制您的指令是在内置指令之前还是之后运行。

    这个plunker 展示了如何构建一个在内置ng-click 之前执行的ng-click 指令。代码也如下所示。点击链接时,自定义的ng-click会先运行,然后是内置的ng-click

    index.html

    <!DOCTYPE html>
    <html ng-app="app">
    
      <head>
        <script data-require="jquery@1.9.0" data-semver="1.9.0" src="//cdnjs.cloudflare.com/ajax/libs/jquery/1.9.0/jquery.js"></script>
        <script data-require="angular.js@1.0.7" 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!')
        }
      })
    

    【讨论】:

    • 非常感谢您的详细回复)
    • Buu,我们可以完全停止第一次 ng-click 吗?我的意思是在运行“覆盖”警报后,“内置”不运行。
    • 不要将表达式传递给 ng-click,请参阅 plnkr.co/edit/uROkIcGKLspLnVsjmAKn?p=preview。如果您必须通过 s/t,则不要处理它,例如$scope.alert = function() {}.
    • 这不是正确答案,看看下面的 Eric Chen 吧!
    • 同意 JackNova,这个答案不正确。 * 您可以覆盖/替换所有指令,如下面的@eric-chen 所示 * 此示例方法会遇到问题 - 您不能在同一元素上使用多个指令来请求隔离范围或设置模板。 Eric 的方法也解决了这个问题
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 2016-08-30
    • 2015-11-15
    • 2021-07-18
    • 1970-01-01
    相关资源
    最近更新 更多