在弹出框外单击时隐藏 Angular UI Bootstrap 弹出框

Hide Angular UI Bootstrap popover when clicking outside of it

我正在尝试手动关闭 bootstrap 弹出窗口,以便在我单击 documentbody 上的任何非弹出窗口时将其关闭。

我发现最接近完成此操作的方法是创建指令 (found this answer),但如果变量为 true.

谁能帮我弄清楚如果我单击不是弹出窗口的任何内容,如何关闭它?

我不介意使用 jQuery $(document).click(function(e){}); 我只是不知道如何结束。

<div id="new_button" popover-template="plusButtonURL" popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>

通常 popover-trigger="focus" 可以解决问题,但是我的弹出窗口包含需要单击的内容。如果我使用 focus 触发器,我的弹出窗口中有一个 ng-click 会被忽略,所以我正在寻找一种不太传统的方法来解决这个问题。

有一个名为 popover-trigger 的 属性,您可以将 属性 focus 分配给它。

<button 
      popover-placement="right" 
      popover="On the Right!" 
      popover-trigger="focus" 
      class="btn btn-default">
   Right
</button>

这很管用! :)

编辑: 要允许单击工具提示而不触发焦点丢失,请考虑一种方法 similar to this

如果您希望它在 angular 中工作,请尝试创建您自己的触发器定义。关于如何做到这一点的建议可以是 found here.

已编辑:

Plunker Demo

这是它的工作原理(仍然很长且详尽的解释):

  1. 创建允许您定位触发元素的自定义指令。
  2. 创建一个添加到正文的自定义指令,它将找到触发元素并在单击时触发自定义事件。

创建自定义指令以触发元素为目标:

您需要从打开弹出窗口的元素(在演示中是按钮)触发自定义事件处理程序。挑战在于弹出框作为同级附加到此元素,我始终认为当您遍历 DOM 并期望它具有特定结构时,事情更有可能被破坏。有多种方法可以定位触发元素,但我的方法是在单击元素时向该元素添加一个唯一的 class 名称(我选择 'trigger')。在这种情况下一次只能打开一个弹出窗口,因此使用 class 名称是安全的,但您可以根据自己的喜好进行修改。

自定义指令

app.directive('popoverElem', function(){
  return{
    link: function(scope, element, attrs) {
      element.on('click', function(){
        element.addClass('trigger');
      });
    }
  }
});

应用于按钮

<button popover-template="dynamicPopover.templateUrl" popover-title="{{dynamicPopover.title}}" class="btn btn-default" popover-elem>Popover With Template</button>

为文档正文(或任何其他元素)创建自定义指令以触发弹出窗口关闭:

最后一部分是创建一个自定义指令,该指令将定位触发元素并在单击它所应用的元素时触发自定义事件以关闭弹出框。当然,您必须从 'trigger' 元素中排除初始点击事件,以及您希望在弹出窗口内部与之交互的任何元素。因此,我添加了一个名为 exclude-class 的属性,这样您就可以定义一个 class,您可以将其添加到应忽略其点击事件的元素(不会导致弹出窗口关闭)。

为了清理,当事件处理程序被触发时,我们删除添加到触发器元素的触发器 class。

app.directive('popoverClose', function($timeout){
  return{
    scope: {
      excludeClass: '@'
    },
    link: function(scope, element, attrs) {
      var trigger = document.getElementsByClassName('trigger');

      function closeTrigger(i) {
        $timeout(function(){ 
          angular.element(trigger[0]).triggerHandler('click').removeClass('trigger'); 
        });
      }

      element.on('click', function(event){
        var etarget = angular.element(event.target);
        var tlength = trigger.length;
        if(!etarget.hasClass('trigger') && !etarget.hasClass(scope.excludeClass)) {
          for(var i=0; i<tlength; i++) {
            closeTrigger(i)
          }
        }
      });
    }
  };
});

我将其添加到 body 标签中,以便整个页面*充当弹出窗口的可关闭背景:

<body popover-close exclude-class="exclude">

并且,我在弹出框的输入中添加了排除 class:

<input type="text" ng-model="dynamicPopover.title" class="form-control exclude">

所以,有一些调整和陷阱,但我会留给你:

  1. 您应该在 popover-close 指令的 link 函数中设置默认排除 class,以防未定义。
  2. 你需要知道 popover-close 指令是元素绑定的,所以如果你删除我在 html 和 body 元素上设置的样式以给它们 100% 的高度,你可以 'dead areas' 在你的视口中,如果你的内容没有填满它。

已在 Chrome、Firefox 和 Safari 中测试。

更新:在 1.0 版本中,我们添加了一个名为 outsideClick 的新触发器,当用户在弹出框外单击时,它会自动关闭弹出框或工具提示或工具提示。

从 0.14.0 版本开始,我们添加了通过 tooltip-is-openpopover-is-open 属性以编程方式控制何时打开或关闭 tooltip/popover 的功能。

您可以使用:

标记

<div ng-app="Module">
    <div ng-controller="formController">
        <button uib-popover-template="dynamicPopover.templateUrl" popover-trigger="focus" 
          popover-placement="left" type="button" class="btn btn-default">
             Popover With Template
        </button>

        <script type="text/ng-template" id="myPopoverTemplate.html">
            <div>
                <span>prasad!!</span>
            </div>
        </script>
    </div>
</div>

Javascript

<script type="text/javascript">
    var app = angular.module("Module", ['ui.bootstrap']);
    app.controller("formController", ['$scope', function($scope) {
        $scope.dynamicPopover = {
            templateUrl: 'myPopoverTemplate.html'
        };
    }]);
</script>

自 Angular UI Bootstrap 1.0.0 以来,有一个新的 outsideClick 工具提示和弹出窗口触发器(在 this pull request. In Angular UI Bootstrap 2.0.0, the popover-trigger has been modified to use angular expressions (Changelog 中引入),所以该值必须放在引号中。此代码将适用于当前版本的 angular-ui:

<div id="new_button" uib-popover-template="plusButtonURL" popover-trigger="'outsideClick'"
    popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>

此代码适用于旧版本的 Angular UI Bootstrap(2.0.0 之前):

<div id="new_button" uib-popover-template="plusButtonURL" popover-trigger="outsideClick"
    popover-placement="right" popover-append-to-body="true" popover-animation="false">+</div>

Angular boostrap ui 新版本 1.x 具有外部点击功能。将其升级到新版本。

<button uib-popover-template="updatePassword.templateUrl" popover-title="Update Password" popover-trigger="outsideClick" popover-placement="right" popover-append-to-body="true">Click here</button>

对我有用。

如果弹出窗口中有任何提交按钮或点击事件,焦点将不起作用。所以这个有用的方法。

你要找的是

<button
      popover-trigger="outsideClick" 
      class="btn btn-default">
   Right
</button>

来自文档 - outsideClick 触发器将导致弹出窗口在单击时切换,并在单击其他内容时隐藏。

popover-trigger="'outsideClick'" 这会很完美。

popover-trigger="outsideClick"这个不会。

我花了 1 天的时间才弄清楚为什么它对我不起作用。

这是因为他们使用此代码进行检查,"if (trigger === 'outsideClick')"

这是由于强类型检查,我们需要将其作为 String

传递

我遇到了同样的问题,popover-trigger="'outsideClick'" 对我有用。有趣的是文档没有说明这个问题。

向您的某些背景元素添加 onclick="void(0)" 行为,点击这些元素后弹出窗口将消失。

看看https://github.com/angular-ui/bootstrap/issues/2123

'$uibTooltipProvider'setTriggers方法中的'outsideClick'选项呢.文档说 "The outsideClick trigger will cause the tooltip to toggle on click, and hide when anything else is clicked." Documentation

1) 使用 ng-bootstrap 作为 Popover。

2) 将ng-bootstrap版本升级到3.0.0或以上。 即 npm install --save @ng-bootstrap/ng-bootstrap@3.0.0

3) 更新后可以使用Ngbpopover的[autoClose]功能

<button type="button" class="btn btn-outline-secondary" popoverTitle="Pop title" [autoClose]="true" ngbPopover="Click anywhere or press Escape to close (try the toggling element too)">Click to toggle</button>

4) 希望对您有所帮助!