【问题标题】:closing dropdown single or multiselect when clicking outside单击外部时关闭下拉单选或多选
【发布时间】:2014-12-24 09:18:18
【问题描述】:

我正在尝试关闭我的多选下拉菜单。下面是我正在尝试的代码:

element.bind('click', function (event) {
    event.stopPropagation();
});

$document.bind('click', function () {
    $scope.opened = false;
    $scope.$apply();
});

但是一旦我在下拉窗口之外单击。单击会触发多次单击事件,并且对于下面的代码块的每次单击都会被调用 n 次,例如 = 40、90 等,我猜它等于窗口中的元素数:

$document.bind('click', function () {
    $scope.opened = false;
    $scope.$apply();
});

我什至在 document.bind 之后尝试了event.stopPropagation(),但没有成功。

我在为多选创建的指令的链接函数中编写了这些代码块。

【问题讨论】:

  • 我建议添加这个奇怪行为的演示。否则很难帮你。 plnkr.co/edit

标签: angularjs


【解决方案1】:

我认为这会解决你的问题

post: function ($scope, element, attrs, controller) { 
  element.on("click", function(){
    console.log("in element Click event");
    $scope.onElementClick = true;
    $document.on("click", $scope.onClick);
  });

  $scope.onClick = function (event) {
    if($scope.onElementClick)
    {
      $scope.onElementClick = false;
      return;
    }
    $scope.$apply(attrs.clickAnywhereButHere)
    $document.off("click", $scope.onClick);
  };
}

【讨论】:

  • 您好 Vaibhav,感谢您的回复,但即使我单击下拉箭头,上面的代码也会关闭下拉菜单,因为它在内部调用 onDocumentClick() 方法。所以我看不到下拉菜单本身
  • 我还在等待解决方案。
  • 我无法理解您的问题,因为您的信息不完整。如果您为此提供 plunker,那么我将能够帮助您。
  • link for dropdown plnkr 是类似的 plnkr 链接,我在堆栈溢出中也发现了与Question 下面的链接相同的问题,解决方案 B 与我的相同,我面临相同的性能影响。一旦点击导致超过 50 次点击事件。
  • 嗨 Vibhav,这个解决方案确实提高了性能,并且每次它只导致一次点击事件。但是,如果您单击下拉菜单说 D1 并通过单击下拉菜单本身将其关闭,我仍然会发现一个问题(例如,您从菜单中选择某些内容并关闭下拉菜单)。现在如果你再次点击 D1 它不会打开,我尝试调试它,发现 $scope.onClick = function (event) 被触发了两次
【解决方案2】:

我已经使用下面的单选和多选下拉解决方案解决了我的问题。

  1. 以下解决方案可用于生产,因为它不会对性能产生任何影响

我的设计方法我为单选创建了如下指令:

.directive("selection", ['$document',
        function ($document) {
       -- your variable initialization--
       --any other method if you have like I have --
         $scope.change = function (item) {
          -------- my implementation 
     };
     $scope.selected = function (item) {
         -------- my implementation
    };
//Actual click event should be handled in link function
function link($scope, element, attributes, ngModel) {
   --other methods if you have any--
            element.bind('click', function(event) {
                    $scope.onElementClick = true;
                    $document.on("click", $scope.onClick);
                });

                 $scope.onClick = function (event) {
                    if($scope.onElementClick && $scope.opened)
                    {
                      $scope.onElementClick = false;
                      return;
                    }
                    $scope.opened = false;
                    $scope.$apply(attributes.selection);
                    $document.off("click", $scope.onClick);
                  };
                }
                return {
                restrict: 'E',
                controller: controller,
                link: link,
               scope: true,
               require: "ngModel",
               templateUrl: 'your template file(e.g: filename.tpl.html)'
        };

因此,只有当您单击任何单个选择下拉菜单时,上面的代码才会将单击事件与文档绑定,并且由于 $document.off("click", $scope.onClick);

对于多选下拉菜单,您需要处理特殊情况,例如,如果您单击元素,则不应关闭下拉菜单,否则您一次不能选择多个选项。因此,如果在元素内单击它,则必须停止单击事件的传播。请在您点击链接功能内的事件处理中进行以下更改:

.directive("multiSelection", ['$document',
        function ($document) {
       -- your variable initialization--
       --any other method if you have like I have --
         $scope.change = function (item) {
          -------- my implementation 
     };
     $scope.selected = function (item) {
         -------- my implementation
    };
//Actual click event should be handled in link function
function link($scope, element, attributes, ngModel) {
   --other methods if you have any--
element.bind('click', function(event) {
                $document.on("click", $scope.onClick);
                event.stopPropagation();
            });

            $scope.onClick = function (event) {
                $scope.opened = false;
                $scope.$apply(attributes.multiSelect);
                $document.off("click", $scope.onClick);
            };
         }

        return {
            restrict: 'E',
            controller: controller,
            link: link,
            require: "ngModel",
            templateUrl: 'your template file(e.g: filename.tpl.html)'
        };

希望对你有帮助

【讨论】:

    猜你喜欢
    • 2017-03-23
    • 1970-01-01
    • 2023-02-23
    • 2021-09-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    相关资源
    最近更新 更多