Обработка нескольких компонентов с событиями нажатия в Angular - PullRequest
0 голосов
/ 31 августа 2018

Эта проблема сводила меня с ума. У меня есть два компонента, которые оба являются переключаемыми раскрывающимися списками на одной странице. У меня есть что-то подобное для обоих компонентов:

@HostListener('click', ['$event'])
clickInside() {
  event.stopPropagation();
  this.showMenu = true;
}

@HostListener('document:click')
clickOutside() {
  if (this.showMenu) {
    this.showMenu = false;
  }
}

Это прекрасно работает для одного компонента, но когда у меня есть два компонента на одной странице, то нажатие на другой компонент оставляет первый компонент открытым, и в результате они оба открываются одновременно, что я не хочу. Причина, конечно, в event.stopPropagation () , но без этого щелчок внутри компонента также будет щелчком внутри документа.

1 Ответ

0 голосов
/ 31 августа 2018

Когда мы щелкаем внутри компонента - он должен быть открыт, когда щелчок был снаружи - он должен быть закрыт.

  constructor(private elementRef: ElementRef){}

  @HostListener('click')
  clickInside() {
    this.showMenu = true;
  }

  @HostListener('document:click', ['$event'])
  clickOutside(event) {
    if (this.showMenu && this.isClickOutside(event)) {
      this.showMenu = false;
    }
  }

  private isClickOutside(event: MouseEvent): boolean {
    return !this.elementRef.nativeElement.contains(event.target);
  }

У этого решения есть по крайней мере один недостаток - каждый компонент с прослушивателем на документе приведет к циклу обнаружения изменения дополнения. Чтобы предотвратить это, мы должны обработать событие вне угла, но изменить состояние внутри.

private readonly onDestroy$ = new Subject();

constructor( private ngZone: NgZone,) {}

ngOnInit() {
    this.ngZone.runOutsideAngular(() => {
      fromEvent(window.document, 'click')
        .pipe(
          filter(
            (event: MouseEvent) =>
              this.isOpen() && this.isClickOutside(event)
          ),
          takeUntil(this.onDestroy$),
        )
        .subscribe(() => {
          this.ngZone.run(() => {
            this.close();
          });
        });
    });
  }

ngOnDestroy() {
    this.onDestroy$.next();
    this.onDestroy$.complete();
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...