Когда мы щелкаем внутри компонента - он должен быть открыт, когда щелчок был снаружи - он должен быть закрыт.
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();
}