如何在Angular 7中检测元素外部的单击? [英] How to detect click outside of an element in 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
优雅地触发事件.它只是将要监听的元素作为第一个参数,可以是window
,document
,body
或任何其他元素引用.对于第二个参数,它采用了我们要监听的事件,在本例中为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屋!