7

这是一个指令,我试图在其中禁用基于模型值的链接:

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/

4

3 回答 3

9

使用event.stopImmediatePropagation.

来自MDN

如果多个侦听器附加到同一事件类型的同一元素,则按添加它们的顺序调用它们。如果在一次这样的调用中调用了 event.stopImmediatePropagation(),则不会调用剩余的侦听器。

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

  return true;
});
...

工作小提琴

于 2013-07-24T10:12:50.223 回答
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在运行内部代码之前检查是否为 false tellAboutIt()。例如:

$scope.tellAboutIt = function(){
    if ($scope.disableIt === false) {
        $window.alert('ngClick fired. This alert should not show when disabled.');
    }
};
于 2013-07-24T00:48:51.800 回答
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>
于 2013-07-24T02:54:14.723 回答