nicoschuck
nicoschuck

Reputation: 199

Angular 6 Blur Event for multiple DOMS

I have a button which should show a separate div. The div should disappear if I click on anything else than my div. I tried to do that with blur but if I click on anything else than my button (also if I click on my div) the div disappears.

<button mat-button (click)="open=true;" (blur)="open=false;"></button>
<div *ngIf="open">content</div>

What I want is the following:

1)click on button -> div appears

2)click on elements inside the div (for example an input) and interact with it

3)click on anything else -> div disappears

On other pages some people mentioned to use tabindex="0" but I didn´t get how to use that. Is it possible to connect the div to the button for blur event?

Upvotes: 1

Views: 3353

Answers (1)

AVJT82
AVJT82

Reputation: 73357

In these cases I would make a directive, they are neat and re-usable and by googling "click outside directive angular" you can find some answers. Here though you need to watch on two elements, so the directive wouldn't be as neat, but the following works.

Give your button some class name, for example open-button. We will use this in our directive. So make a directive as follows (and mark in your declarations array):

import { Directive, ElementRef, Output, EventEmitter, HostListener } from '@angular/core';

@Directive({
  selector: '[isOutside]'
})
export class IsOutsideDirective {
  constructor(private elementRef: ElementRef) { }

  @Output()
  public isOutside = new EventEmitter();

  // watch for click events
  @HostListener('document:click', ['$event.target'])
  public onClick(targetElement) {
    if (this.elementRef) {
      // see if clicked element is the target element OR the button
      const clickedInside = this.elementRef.nativeElement.contains(targetElement) || 
                            targetElement.classList.contains('open-button');
      if (!clickedInside) {
        this.isOutside.emit(true);
      }
    }
  }
}

Then use it in your div that you want to hide/show:

<div *ngIf="open" (isOutside)="hide($event)" ....

hide() would then set open to false, as isOutside only emits when clicked outside of those two elements:

hide(event) {
  this.open = false;
}

Your button will also toggle open:

<button class="open-button" (click)="open = true">Show div</button>

DEMO: StackBlitz

Upvotes: 2

Related Questions