Angular 封装和点击外部指令

Angular encapsulation and click-outside directive

问题:我需要添加一种方法来绑定和关闭侧边栏菜单,如果用户点击它以外的地方。

我创建了一个指令(Something )来检查点击是否绑定在我的元素之外,但是当用户准确点击侧边栏上我的超棒字体图标时,它被认为是外部点击和菜单未打开(该指令运行良好,我点击按钮填充进行检查)...

我想这是我的指令的问题,由 angular 封装引起...

我的代码:

<aside [ngClass]="{'open': menuStatus}" (clickOutside)="menuStatus = false">
    <button (click)="menuStatusToggle()">
        <fa-icon [icon]="['fas', 'bars']" *ngIf="!menuStatus"></fa-icon>
        <fa-icon [icon]="['fas', 'times']" *ngIf="menuStatus"></fa-icon>
    </button>
    (Menu Content...)
</aside>

绑定事件:

@HostListener('document:click', ['$event.target'])
  public onClick(targetElement) {

    // Variable content always false when click on icon of _elementRef
    const clickedInside = this._elementRef.nativeElement.contains(targetElement);

    if (!clickedInside) {
      this.clickOutside.emit(null);
    }
  }

有人有建议吗?封装真的有问题?

您需要更正您的 onClick 函数的参数,它应该是这样的:

@HostListener('document:click', ['$event.target'])
public onClick(event) {

  const clickedInside = this._elementRef.nativeElement.contains(event.target);

  if (!clickedInside) {
    this.clickOutside.emit(null);
  }
}

为了确保超棒的字体图标不会捕捉到点击事件,在组件中定义如下样式CSS:

fa-icon {
  pointer-events: none;
}

有了那个样式属性,按钮接收到点击事件,然后就可以正确处理了。

有关演示,请参阅 this stackblitz


另一种解决方案是处理宿主元素上的单击事件,并停止传播。因此,所有到达文档的点击事件都在宿主元素之外:

@HostListener('click', ['$event'])
public onHostClick(event: Event) {
  event.stopPropagation();
}

@HostListener('document:click', ['$event'])
public onDocumentClick(event: Event) {
  this.clickOutside.emit(null);
}

有关演示,请参阅 this stackblitz