如何在外部单击时关闭Angular-bootstrap popover

时间:2015-09-29 19:10:30

标签: javascript angularjs twitter-bootstrap angular-ui-bootstrap angular-bootstrap

我试图在点击弹出窗口外的任何地方时关闭我的Angular-bootstrap popover。根据这个问题的答案,现在可以通过利用新的popover-is-open属性来完成(在版本0.13.4中):Hide Angular UI Bootstrap popover when clicking outside of it

目前我的HTML看起来像这样:

<div
  ng-click="level.openTogglePopover()"
  popover-template="level.changeLevelTemplate"
  popover-trigger="none"
  popover-placement="right"
  popover-is-open="level.togglePopover">
  <button class="btn btn-default btn-xs" type="button">
    <span class="glyphicon glyphicon-sort"></span>
  </button>
</div>

...和我的相关控制器代码:

vm.togglePopover = false;

vm.openTogglePopover = function() {
  vm.togglePopover = !vm.togglePopover;
};

这对于在单击上面引用的按钮时打开/关闭弹出窗口非常有用。我的问题是,当点击弹出窗口外的任何地方时,我如何扩展此功能以关闭弹出窗口?我如何设置事件处理来完成此任务?

5 个答案:

答案 0 :(得分:13)

由于angular-ui 1.0.0,工具提示和弹出窗口有一个新的outsideClick触发器(在this pull request中引入:

<div
  uib-popover-template="level.changeLevelTemplate"
  popover-trigger="outsideClick"
  popover-placement="right">
  <button class="btn btn-default btn-xs" type="button">
    <span class="glyphicon glyphicon-sort"></span>
  </button>
</div>

答案 1 :(得分:11)

首先,如果您希望弹出窗口在任何点击时关闭,而不仅仅是弹出窗口外的弹出窗口,您可以使用现有的UI-Bootstrap代码执行此操作:

<button class="btn btn-default btn-xs" type="button"
        popover-template="level.changeLevelTemplate"
        popover-trigger="focus"
        popover-placement="right">
  <span class="glyphicon glyphicon-sort"></span>
</button>

这里的诀窍是放弃周围的<div>并将popover-trigger="focus"放在按钮上。

如果您只需要为弹出窗口内容之外的点击关闭popover,那么它将更加困难。你需要一个新的指令,如下所示:

app.directive('clickOutside', function ($parse, $timeout) {
  return {
    link: function (scope, element, attrs) {
      function handler(event) {
        if(!$(event.target).closest(element).length) {
          scope.$apply(function () {
            $parse(attrs.clickOutside)(scope);
          });
        }
      }

      $timeout(function () {
        // Timeout is to prevent the click handler from immediately
        // firing upon opening the popover.
        $(document).on("click", handler);
      });
      scope.$on("$destroy", function () {
        $(document).off("click", handler);
      });
    }
  }
});

然后,在弹出模板中,使用最外层元素的指令:

<div click-outside="level.closePopover()">
   ... (actual popover content goes here)
</div>

最后,在您的控制器中,实现closePopover功能:

vm.closePopover = function () {
  vm.togglePopover = false;
};

我们在这里做的是:

  • 我们正在聆听对文档的任何点击,如果点击位于我们添加close-popover指令的元素之外:
    • 我们调用的任何代码都是close-popover
    • 的值
  • 当指令的范围被销毁时(即弹出窗口关闭时),我们也会自行清理,以便我们不再处理点击。

这不是最干净的解决方案,因为您必须从弹出模板中调用控制器方法,但这是我提出的最佳解决方案。

答案 2 :(得分:2)

如果我理解正确,当用户点击几乎任何地方(除了在弹出窗口内部)时,你想要关闭弹出窗口,除非实际关闭按钮。这可以通过事件监听器完成:

$('html').click(function() {
    if(!$(event.target).is('#foo')) {
        // Code to hide/remove popovers
    }
});

查看此plunkr

或者,在您的具体情况中:

$('html').click(function() {
    if(!$(event.target).is('.my-popover-class')) {
        vm.togglePopover = false;
    }
})

答案 3 :(得分:1)

您需要自己进行事件处理,就像使用新的*-is-open属性一样,没有事件处理。

如果您不需要对打开/关闭弹出窗口进行编程控制,那么您可以使用内置的focus触发器来提供您想要的内容。

答案 4 :(得分:1)

  

单击弹出窗口外的任何位置时关闭弹出框

前段时间我发现这个答案很有用:How to dismiss a Twitter Bootstrap popover by clicking outside?

我在我的一个演示中使用的代码(混合angularjQuery事件处理可能不推荐)是特定于我的需求但可能会有一些想法:

  app.directive("eventlistener", function($rootScope) {
    $(window).resize($rootScope.closeAllPopovers); // because Bootstrap popovers don't look good when misplaced

    return {
      link: function(scope, element, attrs) {
        $('body').on('mouseup touchend', $rootScope.closeAllPopovers);
      }
    };
  });

  $rootScope.closeAllPopovers = function (e) {
    $('[data-toggle="popover"]').each(function () {
      if (e) {
        if (!$(this).is(e.target) && $(this).has(e.target).length === 0 && $('.popover').has(e.target).length === 0) {
          $(this).popover('hide');
        }
      } else {
        // No event passed - closing all popovers programmatically
        $(this).popover('hide');
      }
    });
  };

我还建议看看之间的区别: