如何在Angular 7中检测元素外部的单击? [英] How to detect click outside of an element in Angular 7?

查看:394
本文介绍了如何在Angular 7中检测元素外部的单击?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

单击open panel按钮时,此div将在页面上动态显示为东面板. bool showEastPanel变量是用于打开和关闭东部面板的变量.我正在尝试使用(clickoutside)关闭面板(将showEastPanel设置为false),但是打开的面板首先在Angular挂钩上运行,并且面板设置为true,然后设置为false,并且面板不显示.有什么办法使"clickoutside"范围不包括按钮?

This div will be dynamically shown on the page as an east panel when the open panel button is clicked. The bool showEastPanel variable is what is used to open and close the east panel. I am trying to use (clickoutside) to close the panel (setting showEastPanel to false) however the open panel runs first on the Angular hook and the panel is set to true then false and the panel doesn't display. Is the any way to scope `clickoutside' to not include the button?

<div [ngClass]="{'d-none': !showEastPanel, 'east-panel-container': showEastPanel}" (clickOutside)="ClosePanel()">
<div id="east-panel">
  <ng-template #eastPanel></ng-template>
</div>

<button (click)="ShowPanel()">Open Panel</button>

推荐答案

以下是工作演示的链接: Stackblitz演示

Here is the link to the working demo: Stackblitz Demo

我将使用Angular推荐的方法来做到这一点,该方法在没有DOM访问的环境中也很容易开发应用程序,我的意思是

I would do this by using the Angular recommended approach which is also easy to develop apps in environments with no DOM access, I mean Renderer 2 class which is an abstraction provided by Angular in the form of a service that allows manipulating elements of your app without having to touch the DOM directly.

在这种方法中,您需要将Renderer2注入到您的组件构造函数中,通过Renderer2我们可以通过listen优雅地触发事件.它只是将要监听的元素作为第一个参数,可以是windowdocumentbody或任何其他元素引用.对于第二个参数,它采用了我们要监听的事件,在本例中为click,而第三个参数实际上是我们通过箭头函数执行的回调函数.

In this approach, you need to inject Renderer2 into your component constructor, which the Renderer2 lets us to listen to triggered events elegantly. It just takes the element you're going to listen on as the first argument which can be window, document, body or any other element reference. For the second argument it takes the event we're going to listen on which in this case is click, and the third argument is actually the callback function which we do it by arrow function.

this.renderer.listen('window', 'click',(e:Event)=>{ // your code here})

解决方案的其余部分很容易,您只需要设置一个布尔标志即可保持菜单(或面板)可见性的状态,我们应该做的就是在外部单击该标志时将false分配给该标志菜单中的

The rest of the solution is easy, you just need to set a boolean flag which keeps the status of the menu (or panel) visibility, and what we should do is to assign false to that flag when it's clicked outside of the menu.

HTML

<button #toggleButton (click)="toggleMenu()"> Toggle Menu</button>

<div class="menu" *ngIf="isMenuOpen" #menu>
I'm the menu. Click outside to close me
</div>

app.component.ts

export class AppComponent {
  /**
   * This is the toogle button elemenbt, look at HTML and see its defination
   */
  @ViewChild('toggleButton') toggleButton: ElementRef;
  @ViewChild('menu') menu: ElementRef;

  constructor(private renderer: Renderer2) {
    /**
     * This events get called by all clicks on the page
     */
    this.renderer.listen('window', 'click',(e:Event)=>{
         /**
          * Only run when toggleButton is not clicked
          * If we don't check this, all clicks (even on the toggle button) gets into this
          * section which in the result we might never see the menu open!
          * And the menu itself is checked here, and it's where we check just outside of
          * the menu and button the condition abbove must close the menu
          */
        if(e.target !== this.toggleButton.nativeElement && e.target!==this.menu.nativeElement){
            this.isMenuOpen=false;
        }
    });
  }

  isMenuOpen = false;

  toggleMenu() {
    this.isMenuOpen = !this.isMenuOpen;
  }
}

同样,如果您想观看正常的演示,请使用此链接: Stackblitz演示

Again, if you like to see the working demo, use this link: Stackblitz Demo

这篇关于如何在Angular 7中检测元素外部的单击?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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