Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does Node.contains() work when working with shadow DOM in Angular 2?

I couldn't find this anywhere in the docs, but my Node.contains() function is not working when I click something inside a component that is part of a parent component.

My parent component looks like this:

<div class="body">
    <div class="item" *ngFor="let item of sortedItems;">
        <cv-checkbox></cv-checkbox>
        <cv-svg-icon></cv-svg-icon>
    </div>

    <div class="drop-zones" *ngFor="let zone of sortedItems.length + 1 | numberToArrayPipe;>
        <div class="drop-zone"></div>
    </div>
</div>

As you can see i have two Angular components inside my parent component: cv-checkbox and cv-svg-icon. I've added a directive to my parent component that looks like this:

<cv-layer-manager cvClickOutside (clickOutside)="toggleLayerManager()"></cv-layer-manager>

Where i check if the clicked Node is contained by the parent like this:

@HostListener('document:click', ['$event']) public onClick(event: MouseEvent) {
    const clickedInside = this._elementRef.nativeElement.contains(event.target);
    if (!clickedInside) {
        this.clickOutside.emit();
    }
}

If i click normal HTML components everything works as expected but not when i'm clicking on an Angular component. Is it correct that contains doesn't check inside the Angular component?

like image 932
Martijn van den Bergh Avatar asked Dec 26 '17 10:12

Martijn van den Bergh


1 Answers

I had a similar issue with a datepicker. To fix this problem I added allowClose property to current component.

@ViewChild('element') elementRef: ElementRef;
private allowClose = true;

Then I added another HostListener that listens only to events of current component.

@HostListener('click', ['$event'])
clickInside(event: any) {
  this.allowClose = false;
}

Then I modified my clickOutside method to handle close only if allowClose is true and then set allowClose back to true again.

@HostListener('document:click', ['$event'])
clickOutside(event: any) {
  if (!this.elementRef.nativeElement.contains(event.target) && this.allowClose) {
    this.handleClose();
  }
  this.allowClose = true;
}

That's it!

like image 122
Michal Cumpl Avatar answered Nov 15 '22 05:11

Michal Cumpl