How to Detect Click Outside of an Element in Angular

How to detect click outside of an element in Angular?

Here is the link to the working demo: Stackblitz Demo

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.

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})

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;
}
}

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

Detect click outside Angular component

import { Component, ElementRef, HostListener, Input } from '@angular/core';

@Component({
selector: 'selector',
template: `
<div>
{{text}}
</div>
`
})
export class AnotherComponent {
public text: String;

@HostListener('document:click', ['$event'])
clickout(event) {
if(this.eRef.nativeElement.contains(event.target)) {
this.text = "clicked inside";
} else {
this.text = "clicked outside";
}
}

constructor(private eRef: ElementRef) {
this.text = 'no clicks yet';
}
}

A working example - click here

Click outside angular component

I used a directive to a similar situation.
To install:

npm install --save ng-click-outside

Then import in your module

import { ClickOutsideModule } from 'ng-click-outside';

@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, ClickOutsideModule],
bootstrap: [AppComponent]
})
class AppModule {}

In your component

@Component({
selector: 'app',
template: `
<div (clickOutside)="onClickedOutside($event)">Click outside this</div>
`
})
export class AppComponent {
onClickedOutside(e: Event) {
console.log('Clicked outside:', e);
}
}

It has some options. You can see it in https://www.npmjs.com/package/ng-click-outside

Regards

Angular 6 - click outside menu

As suggested in this answer, you can detect the document click events with HostListener. To make sure that mouse clicks don't reach the document when the menu is clicked, you should stop the propagation of the event in the click event handler set on the aside element:

<aside [hidden]="!menu" (click)="handleAsideClick($event)">
@HostListener('document:click', ['$event']) clickout(event) {
// Click outside of the menu was detected
...
}

handleAsideClick(event: Event) {
event.stopPropagation(); // Stop the propagation to prevent reaching document
...
}

detect when a child component is clicked outside

Use stopPropagation event

app.html

<div (click)="fn_selectIndex($event, -1)" style="height:100vh">
<ng-container *ngFor="let item of myArray; let i=index" >
<mycomponent (click)="fn_selectIndex($event, i)" [myArray]="item" [indexSelected]="indexSelected" [index]="i"></mycomponent>
<br>
</ng-container>
</div>

app.ts

export class AppComponent  {
name = 'Angular';
myArray:any=[1,2,3,4,5];
indexSelected=null;s

fn_selectIndex(event, i:any){
this.indexSelected=i;
event.stopPropagation();
}
}

Reference: https://stackblitz.com/edit/angular-edld9f?file=src/app/app.component.ts

Detect click outside of Angular application which runs in an iframe

Thanks @Msk Satheesh and @MikeOne, with the hints of both of you guys combined I got it running!

The thing is that I can really address the (outer) wordpress page by window.parent. But this only works because both run in the same domain. Combined with the code Msk Satheesh posted in his first comment it works. And I don't even need to run anything outside of Angular. In my modal dialog component in Angular I put the following code:

  constructor(public dialogRef: MatDialogRef<ResultsDialogComponent>, private eRef: ElementRef) {}

ngOnInit(): void {
if(!this.onDocumentClickFunction){
this.onDocumentClickFunction = this.onDocumentClick.bind(this);
}
window.parent.addEventListener( 'click', this.onDocumentClickFunction );
}

onDocumentClick() {
this.dialogRef.close();
this.eRef.nativeElement.click();
}

ngOnDestroy() {
window.parent.removeEventListener( 'click', this.onDocumentClickFunction );
}

And that's it. The elegant thing is that the onDocumentClick() only fires if the click is outside the iFrame. That means I don't need additional logic to find out if the click is inside or outside the iFrame. The line this.eRef.nativeElement.click(); is necessary to bring back the focus to the iFrame. Without that line the modal only disappears if the user clicks into the iFrame himself.



Related Topics



Leave a reply



Submit