单击外部时隐藏 Angular UI Bootstrap 弹出框 [英] Hide Angular UI Bootstrap popover when clicking outside of it

查看:20
本文介绍了单击外部时隐藏 Angular UI Bootstrap 弹出框的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我点击 documentbody 上任何不是弹出框的地方时,我试图手动关闭引导弹出框以使其关闭.

I am trying to manually close a bootstrap popover to get it to close when I click anywhere on the document or body that isn't the popover.

我发现最接近的方法是创建一个指令(找到这个答案),但这是为了如果变量为 truefalse,则手动触发.

The closest thing I have found to accomplishing this is to create a directive (found this answer) but this is for a manual trigger if a variable is true or false.

如果我点击任何不是弹出框的东西,谁能帮我弄清楚如何关闭它?

Could anyone help me figure out how to to get it to close if I click on anything that isn't the popover?

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

I don't mind using jQuery $(document).click(function(e){}); I just have no clue how to call a close.

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

<小时>

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


Normally popover-trigger="focus" would do the trick, however my popover contains content that needs to be clicked on. I have an ng-click inside my popover that get's ignored if I use the focus trigger so I am looking for a not-so-conventional way to get around that.

推荐答案

  1. 创建一个自定义指令,允许您定位触发器元素.
  2. 创建一个自定义指令,该指令添加到正文中,并在点击时找到触发器元素并触发自定义事件.

创建一个自定义指令来定位触发器元素:

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

Create a custom directive to target the trigger element:

You need to trigger the custom event handler from the element that opened the popover (in the demo this is the button). The challenge is that the popover is appended as a sibling to this element and I always think that things have greater potential to break when you are traversing the DOM and expecting it to have a specific structure. There are several ways you can target the trigger element, but my approach is to add a unique classname to the element (I choose 'trigger') when you click on it. Only one popover can be opened at a time in this scenario, so it's safe to use a classname, but you can modify to suit your preference.

自定义指令

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 的属性,以便您可以定义一个类,您可以将其添加到应忽略单击事件(不会导致弹出窗口关闭)的元素中.

Create a custom directive for the document body (or any other element) to trigger the popover close:

The last piece is to create a custom directive that will locate the triggering element and fire the custom event to close the popover when the element it is applied to is clicked. Of course, you have to exclude the initial click event from the 'trigger' element, and any elements you want to interact with on the inside of your popover. Therefore, I added an attribute called exclude-class so you can define a class that you can add to elements whose click events should be ignored (not causing the popover to close).

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

To clean things up, when the event handler is triggered, we remove the trigger class that was added to the trigger element.

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 标记中,以便整个页面*充当弹出窗口的可消除背景:

I added this to the body tag so that the entire page* acts as a dismissible backdrop for the popover:

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

而且,我在弹出窗口的输入中添加了排除类:

And, I added the exclude class to the input in the popover:

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

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

So, there are some tweaks and gotchas, but I'll leave that to you:

  1. 您应该在 popover-close 指令的链接函数中设置一个默认排除类,以防未定义.
  2. 您需要注意 popover-close 指令是元素绑定的,因此如果您删除我在 html 和 body 元素上设置的样式以赋予它们 100% 高度,您的视口中可能会出现死区",如果你的内容没有填满它.

在 Chrome、Firefox 和 Safari 中测试.

Tested in Chrome, Firefox and Safari.

这篇关于单击外部时隐藏 Angular UI Bootstrap 弹出框的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆