html - Otkrivanje klika izvan Angular komponente


Kako mogu otkriti klikove izvan komponente u Angularu?

Odgovor #1

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

Radni primjerak - kliknite ovdje

Odgovor #2

Alternativa odgovoru AMagyara. Ova verzija radi kada kliknete na element koji se uklanja iz DOM-a pomoću ngIf.

http://plnkr.co/edit/4mrn4GjM95uvSbQtxrAS?p=preview

  private wasInside = false;

  @HostListener('click')
  clickInside() {
    this.text = "clicked inside";
    this.wasInside = true;
  }

  @HostListener('document:click')
  clickout() {
    if (!this.wasInside) {
      this.text = "clicked outside";
    }
    this.wasInside = false;
  }

Odgovor #3

Vezanje na klik dokumenta putem @Hostlistener je skupo. Može i imat će vidljiv utjecaj na performanse ako ga previše koristite (na primjer, prilikom izrade prilagođene komponente padajućeg izbornika i imate više instanci stvorenih u obrascu).

Predlažem da se doda @Hostlistener() na događaj klika na dokument samo jednom unutar glavne komponente vaše aplikacije. Događaj bi trebao gurnuti vrijednost kliknutog ciljnog elementa unutar javnog subjekta pohranjenog u globalnoj usluzi utiliteta.

@Component({
  selector: 'app-root',
  template: '<router-outlet></router-outlet>'
})
export class AppComponent {

  constructor(private utilitiesService: UtilitiesService) {}

  @HostListener('document:click', ['$event'])
  documentClick(event: any): void {
    this.utilitiesService.documentClickedTarget.next(event.target)
  }
}

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

Tko god je zainteresiran za kliknuti ciljani element, trebao bi se pretplatiti na javni subjekt naše usluge alata i odjaviti se kada se komponenta uništi.

export class AnotherComponent implements OnInit {

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

  constructor(private utilitiesService: UtilitiesService) { }

  ngOnInit() {
      this.utilitiesService.documentClickedTarget
           .subscribe(target => this.documentClickListener(target))
  }

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

Odgovor #4

Poboljšanje odgovora J. Frankensteina:

  @HostListener('click')
  clickInside($event) {
    this.text = "clicked inside";
    $event.stopPropagation();
  }

  @HostListener('document:click')
  clickOutside() {
      this.text = "clicked outside";
  }

Povezani članci