Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect click outside of an element in Angular?

Tags:

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> </div>  <button (click)="ShowPanel()">Open Panel</button>
like image 549
Lulutho Mgwali Avatar asked Jul 03 '18 08:07

Lulutho Mgwali


People also ask

How do I check my outside Click element?

To detect click outside element with JavaScript, we can use the element's contains method. const specifiedElement = document. getElementById("a"); document. addEventListener("click", (event) => { const isClickInside = specifiedElement.

How can you tell if someone is clicking outside a div?

To detect click outside div using JavaScript, we can check if e. target doesn't equal the inner element. document. getElementById("outer-container").

How do you hide a div when the user clicks outside of it using JavaScript?

To hide an element when clicked outside: Add a click event listener to the document object. On each click, check if the clicked element is outside of the specific element using the contains() method. If the clicked element is outside, hide the original element.


2 Answers

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

like image 141
Mohammad Kermani Avatar answered Sep 21 '22 13:09

Mohammad Kermani


you can do something like this

  @HostListener('document:mousedown', ['$event'])   onGlobalClick(event): void {      if (!this.elementRef.nativeElement.contains(event.target)) {         // clicked outside => close dropdown list      this.isOpen = false;      }   } 

and use *ngIf=isOpen for the panel

like image 40
Sujay Avatar answered Sep 20 '22 13:09

Sujay