0

Problem: I need add a way to bind and close sidebar menu if user click outside that.

I've create a directive (Something like found on this) that check if click is bind outside my element, but when user click exactly on my font-awesome icon on sidebar, it's considered a outside click and menu is not opened (The directive is works good, I checking it clicking on button padding)...

I guess it's a problem on my directive caused by angular encapsulations...

My code:

<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>

Bind event:

@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);
    }
  }

Someone have a suggestion? Encapsulation is really a problem?

Paulo Martins
  • 157
  • 1
  • 9

2 Answers2

1

To make sure that the font-awesome icon does not catch the click event, define the following style in the component CSS:

fa-icon {
  pointer-events: none;
}

With that style attribute, the button receives the click event, which can then be handled correctly.

See this stackblitz for a demo.


An alternative solution is to handle the click event on the host element, and to stop the propagation. As a consequence, all the click events reaching the document are outside the host element:

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

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

See this stackblitz for a demo.

ConnorsFan
  • 70,558
  • 13
  • 122
  • 146
0

You need a correction on the parameter on your onClick function, it should be like:

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

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

  if (!clickedInside) {
    this.clickOutside.emit(null);
  }
}
Andre Knob
  • 821
  • 7
  • 7