点击 div 外部 - 当 div 中含有触发事件的按钮 - AngularJS

3
我使用以下指令来检测点击事件是否发生在一个div之外:
app.directive('clickOut', function ($window, $parse) {
return {
    restrict: 'A',
    link: function (scope, element, attrs) {
        var clickOutHandler = $parse(attrs.clickOut);

        angular.element($window).on('click', function (event) {
            if (element[0].contains(event.target)) return;
            clickOutHandler(scope, {$event: event});
            scope.$apply();
        });
    }
  };
});

在这个 div 中:
             <div class="panel-body" click-out="closeMyPopup()">                 
                <div class="row clearfix">
                    <div class="col-md-12">
                        <div class="form-inline pull-right">
                            <button type="button" class="form-control btn"  ng-click="onCancelAnnouncement()">Cancel</button>
                            <button type="submit" class="form-control btn" ng-click="onSaveAnnouncement()">Save</button>
                        </div>

                    </div>
                </div>

            </div>

当您点击div外部时,closeMyPopup()函数会被触发,这个功能很好。问题是div中有一些按钮可以触发其他函数。由于某种原因,当调用其他函数(例如当点击按钮时)时,会触发点击外部的事件从而调用closeMyPopup()函数。按钮位于div内部,因此不应该调用点击外部的事件。是否有另一个可以使用的指令,具有正确的行为且在触发其他函数时不会触发点击外部的事件?或者我该如何解决这个问题?
我还使用了另一个具有相同问题的指令:
app.directive("outsideClick", ['$document', '$parse', function      ($document, $parse) {
    return {
           link: function ($scope, $element, $attributes) {
        var scopeExpression = $attributes.outsideClick,
            onDocumentClick = function (event) {
                var isChild = $element.find(event.target).length > 0;

                if (!isChild) {
                    $scope.$apply(scopeExpression);
                }
            };

        $document.on("click", onDocumentClick);

        $element.on('$destroy', function () {
            $document.off("click", onDocumentClick);
        });
    }
  }
}]);
2个回答

3

这是因为事件正在传播到Window对象。

- Window
    - document
        - dialog
           - button

在上面的层次结构中,如果最后一个 button 元素发生点击事件,则该事件将向父元素传播,直到达到 Window,然后将关闭您的对话框。
解决方案 1:
通过将事件作为参数传递并调用 event.stopPropagation() 函数,在每个控制器函数中停止事件传播。
<button type="button" class="form-control btn"  ng-click="onCancelAnnouncement($event)">Cancel</button>

...

$scope.onCancelAnnouncement($event) {
    $event.stopPropagation();
}

解决方案2:

让事件传播并检查目标元素:

angular.element($window).on('click', function (event) {
        var target = $(event.target);
        if(target.attr("id") === "anyid") { // or target.hasClass("someclass")
                                            // or target.closest(".some-selector")
            // just ignore
        } else {
            // Do whatever you need 
        }
});

1

确切地说:除非您停止它们的传播,否则事件将呈现给嵌套DOM层次结构中的每个对象。当然,这是有意设计的:JavaScript不假设“我能找到的最内部的人正在听取此事件”是唯一可能感兴趣的人。每个声称正在听取它的人都会听到它,只要他们处于听到它的位置,每个人都会依次听到它...除非其中一个人明确地取消了进一步的传播,JS才会停止寻找其他人发送它。(没有人需要“将事件发送到外部容器”。相反,他们只需要告诉JS不要将其发送即可。)


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接