在自定义指令中禁用ngClick事件处理

时间:2013-07-23 20:34:27

标签: angularjs angularjs-directive

这是一个指令,我试图根据模型值禁用链接:

app.directive('disableable', function($parse){
    return {
        restrict: 'C',
        require: '?ngClick',
        link: function (scope, elem, attrs, ngClick) {
            if (attrs.disable){
                var disable = $parse(attrs.disable);

                elem.bind('click', function (e) {
                    if (disable(scope)){
                        e.preventDefault();
                        return false;
                    }

                    return true;
                });

                scope.$watch(disable, function (val) {
                    if (val){
                        elem.addClass('disabled');
                        elem.css('cursor', 'default');
                    }
                    else {
                        elem.removeClass('disabled');
                        elem.css('cursor', 'pointer');
                    }
                });
             }
         }
     };
});

我希望能够禁用所有链接操作,无论他们是使用简单的href还是ngClick操作。由于preventDefault调用,Hrefs工作正常,但我无法弄清楚如何深入了解ngClick并防止它被触发。我在click事件上执行的绑定不起作用,因为看起来ngClick绑定了我自己无法控制的处理程序。我有什么可以做的吗?

jsFiddle:http://jsfiddle.net/KQQD2/2/

3 个答案:

答案 0 :(得分:8)

使用event.stopImmediatePropagation

来自MDN

  

如果多个侦听器连接到同一个元素   事件类型,按照添加它们的顺序调用它们。如果   在一次这样的调用中,调用event.stopImmediatePropagation(),no   剩下的听众将被召集。

...
elem.bind('click', function (e) {
  if (disable(scope)){
    e.stopImmediatePropagation();
    return false;
  }

  return true;
});
...

WORKING FIDDLE

答案 1 :(得分:4)

您只需将ng-click更改为disableIt || tellAboutIt()即可按原样运行。例如

<a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()">
           ngClick disableable link</a>

完整代码:

HTML (我已删除'禁用'属性,因为它们无法使用,因为它们不适用于锚标记):

<div ng-app="app" ng-controller="appCtrl">
    <a class="disableable" target="_blank" ng-click="disableIt || tellAboutIt()">
       ngClick disableable link</a>
    <br/><br/>
    <a class="disableable" target="_blank" href="http://google.com">
       href disableable link</a>
    <br/><br/>
    <input type="checkbox" ng-model="disableIt" /> Disable links
</div>

Angular (我让你的指令更加紧凑):

app.directive('disableable', function($parse){
    return {
        restrict: 'C',
        link: function (scope, elem, attrs) {
            scope.$watch('disableIt', function (val) {
                if (val) {
                    elem.addClass('disabled');
                    elem.css('cursor', 'default');
                    elem.bind('click', function(e) {
                        e.preventDefault();
                    });
                }
                else {
                    elem.removeClass('disabled');
                    elem.css('cursor', 'pointer');
                    if (typeof elem.attr('ng-click') === 'undefined')
                       elem.unbind('click');
                }
            });
        }
    };
});

JSFiddle:http://jsfiddle.net/KQQD2/4/


或者,您可以在$scope.disableIt内运行代码之前检查tellAboutIt()是否为false。 e.g:

$scope.tellAboutIt = function(){
    if ($scope.disableIt === false) {
        $window.alert('ngClick fired. This alert should not show when disabled.');
    }
};

答案 2 :(得分:0)

我可能会采取略微不同的方式。而不是试图使用另一个指令将自己撬入ng-click。我只是编写自己的ng-click版本并使用它,然后可以使用单独的属性打开/关闭它。如果你这样做,那么你上面写的代码就不需要做太多改变就可以做到这一点,你可以用这个指令代替ng-click。

app.directive('enabled-click', function() {
    return {
       scope: {
          enabledClick: '&',
          enabled: '='
       },
       restrict: 'A',
       link: function( scope, element, attributes ) {
           element.bind('click', function(event) {
               if( scope.enabled ) {
                  if( element.target ) {
                     return true; // external link
                  } else {
                     scope.enabledClick();
                     return false;
                  }
               } else {
                  event.preventDefault();
                  return false;
               }
           } );
           scope.$watch( 'enabled', function(val) {
               if( val ) {
                  element.removeClass('disabled');
               } else {
                  element.addClass('disabled');
               }
           });
       }
    };
});

然后使用它:

<a href="#something" enabled-click="doSomething()" enabled="!disable">Blah</a>