【问题标题】:Dynamically disable all ng-clicks within an element动态禁用元素内的所有 ng-click
【发布时间】:2014-06-22 06:18:15
【问题描述】:

我有一个指令disable-ng-clicks,在某些情况下,我想阻止所有属于该指令子项的 ng-click。这是一些示例标记:

<div disable-ng-clicks> <!-- directive -->
  <a ng-click="someAction()"></a>
  <div ng-controller="myController">
    <a ng-click="anotherAction()"></a>
    <a ng-click="moreActions()"></a>
  </div>
</div>

如果这些是普通的超链接,我可以在 link 函数中执行类似的操作:

function(scope, iElement, iAttrs) {
  var ngClicks = angular.element(iElement[0].querySelectorAll('[ng-click]'));
  ngClicks.on('click', function(event) {
    if(trigger) { // a dynamic variable that triggers disabling the clicks
      event.preventDefault();
    }
  });
}

但这不适用于ng-click 指令。有没有其他方法可以做到这一点?

【问题讨论】:

  • 嗯,您单击的元素不是 div,而是锚点。您应该将它放在每个锚点中或更改指令以禁用 ng-click 子元素。你正在做的方式它只适用于具有指令的元素。
  • 我不确定我是否理解。我可以将点击处理程序附加到父级上,当我点击一个子级时它会执行。
  • 是的,您可以这样做,但您需要更改指令以从具有 It 的元素中查找每个子项。
  • 啊,我明白你在说什么。我更新了问题。

标签: angularjs angularjs-ng-click


【解决方案1】:

我知道这是 2 年前的事,但我需要做类似的事情并想出了一个相当简单的解决方案。

对象:

items: {
    item1 : {
        selected: 0,
        other: 'stuff'
    },
    item2 : {
        selected : 1,
        other: 'stuff'
    }  
}

HTML:

<div ng-repeat="item in items" ng-model="item.selected" ng-click="selectParent($event)">
    <div ng-click="item.selected ? selectChild($event) : null">Child</div>
</div>

功能:

$scope.selectParent = function($event) {
    var itemScope = angular.element($event.currentTarget)scope().item;
    itemScope.selected = !itemScope.selected;
}

$scope.selectChild = function($event) {
    $event.stopPropagation;
    console.log('I only get triggered if parent item is selected');
}

这是我所做的一个非常原始的示例。您可能应该使用为您提供 $scope 而不是 angular.element($event.currentTarget).scope 的指令......无论哪种方式,如果逻辑是我真正想要的,那么简单的内联。您可以根据某个值调用或不调用函数。

【讨论】:

    【解决方案2】:

    这是我能想到的最好的。我创建了一个新指令来替换 ng-click:

     directive('myClick', ['$parse', function($parse) {
      return {
        restrict: 'A',
        compile: function($element, attrs) {
          var fn = $parse(attrs.myClick);
          return function (scope, element, attrs) {
            var disabled = false;
            scope.$on('disableClickEvents', function () {
              disabled = true;
            });
            scope.$on('enableClickEvents', function () {
              disabled = false;
            });
            element.on('click', function (event) {
              if (!disabled) {
                scope.$apply(function () {
                  fn(scope, { $event: event });
                });
              }
            });
          };
        }
      }
    }]);
    

    所以在不同的指令中,我可以:

    if (condition) { 
      scope.$broadcast('disableClickEvents');
    }
    

    当我想重新启用时:

    if (otherCondition) { 
      scope.$broadcast('enableClickEvents');
    }
    

    我不喜欢为 ng-click 使用不同的指令,但这是我能想到的最佳方案。

    【讨论】:

    • 我只是将其标记为答案,因为它满足我的需求。
    【解决方案3】:

    该指令将遍历所有子元素,检查它们是否具有 ng-click 属性,如果有,它将禁用任何已注册的单击事件处理程序:

    directive('disableNgClicks', function(){
      return {
        restrict: 'E',
        link: function(scope, elem, attrs){
          angular.forEach(elem.children(), function(childElem) {
            if (childElem.outerHTML.indexOf("ng-click") > -1) {
              angular.element(childElem).off('click');
            }
          });
        }
      }
    })
    

    Plunker demo

    【讨论】:

    • 我宁愿stopImmediatePropagation而不是取消注册点击事件,因为我想打开和关闭它。不幸的是,我无法让我的指令在 ng-click 之前执行其单击处理程序。我发现priority 指示当两个指令在同一个元素上时的顺序,但是当一个是父元素时,我不确定如何控制首先触发哪个点击处理程序。
    • 是的,在每个元素的基础上阻止 ng-click 事件很容易,但我没有看到任何明显的方法来使用父指令覆盖​​它们的行为,同时允许禁用。正如您所发现的,排序是一个真正的问题。我认为你最好的选择是使用一个范围变量来防止 ng-click 处理程序在设置为 true 时被调用:stackoverflow.com/questions/14545744/…
    • 小评论。该指令必须限制:'A' 才能与@thetallweeks 代码一起使用。
    【解决方案4】:

    你只是因为JS events bubbling而在父级上捕获'click'事件,所以如果你想在所有后代上拦截它,那么你的指令应该获取当前元素的所有后代,监听他们的'click'事件并阻止它如有必要。

    【讨论】:

    • 你能发布示例代码吗?我可以使用 ng-click 抓取所有后代,但即使我尝试运行 event.preventDefault(),也为时已晚,因为 Angular 的 ng-click 已经接管了点击处理程序。
    • ng-click 事件不是默认操作,这是 event.preventDefault() 阻止的。相反,您需要取消注册点击事件——看看我对示例指令的回答。
    • 我更新了问题,这是我的错误。
    猜你喜欢
    • 2017-09-14
    • 1970-01-01
    • 2015-07-01
    • 2016-10-08
    • 2011-07-14
    • 2013-08-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多