Coder Perfect

Outside of the Angular component, detect a click


In Angular, how can I detect clicks outside of a component?

Asked by AMagyar

Solution #1

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

  selector: 'selector',
  template: `
export class AnotherComponent {
  public text: String;

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

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

Click here to see a functional example.

Answered by AMagyar

Solution #2

A different perspective on AMagyar’s response. When you click on an element that is deleted from the DOM with a ngIf, this version works.

Answered by J. Frankenstein

Solution #3

It is expensive to bind to a document click using @Hostlistener. If you overdo it, it can and will have an obvious performance impact (for example, when building a custom dropdown component and you have multiple instances created in a form).

Only apply a @Hostlistener() to the document click event once inside your main app component, in my opinion. The clicked target element’s value should be pushed into a public subject stored in a global utility service by the event.

  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
export class AppComponent {

  constructor(private utilitiesService: UtilitiesService) {}

  @HostListener('document:click', ['$event'])
  documentClick(event: any): void {

@Injectable({ providedIn: 'root' })
export class UtilitiesService {
   documentClickedTarget: Subject<HTMLElement> = new Subject<HTMLElement>()

Subscribe to the public subject of our utilities service if you’re interested in the clicked target element, then unsubscribe when the component is destroyed.

export class AnotherComponent implements OnInit {

  @ViewChild('somePopup', { read: ElementRef, static: false }) somePopup: ElementRef

  constructor(private utilitiesService: UtilitiesService) { }

  ngOnInit() {
           .subscribe(target => this.documentClickListener(target))

  documentClickListener(target: any): void {
     if (this.somePopup.nativeElement.contains(target))
        // Clicked inside  
        // Clicked outside

Answered by ginalx

Solution #4

@J. Frankenstein’s answear is becoming better.

Answered by John Libes

Solution #5

Although the answers provided above are valid, what if you are doing a time-consuming operation after losing concentration on the relevant component? For that, I devised a solution based on two flags, in which the focus out event is triggered only when the focus is lost from the relevant component.

isFocusInsideComponent = false;
isComponentClicked = false;

clickInside() {
    this.isFocusInsideComponent = true;
    this.isComponentClicked = true;

clickout() {
    if (!this.isFocusInsideComponent && this.isComponentClicked) {
        // do the heavy process

        this.isComponentClicked = false;
    this.isFocusInsideComponent = false;

I hope this has been of assistance to you. If I’ve made any mistakes, please let me know.

Answered by Rishanthakumar

Post is based on