#CDK Portal error: Host already has a portal attached

7 messages · Page 1 of 1 (latest)

brisk sparrow
#

Hello,

I have a fully functional Tooltip directive that is implemented with CDK Portal and Overlay.
Once I hover on an element the tooltip appears, but I want to delay the attach a bit. If I try to attach the portal inside a setTimeout it will give the error: Host already has a portal attached.

There is even an extra validation if a portal was attach to prevent the issue happening, but it still gets attached multiple times after a while.


private _overlayRef: OverlayRef | undefined;
private _tooltipRef: ComponentRef<TooltipContainerComponent> | undefined;
private _tooltipPortal: ComponentPortal<TooltipContainerComponent> = new ComponentPortal(TooltipContainerComponent);

@HostListener('mouseenter')
  show(): void {
    if (!this._overlayRef) {
      return;
    }

    // Check if it is already attached
    if (!this._tooltipPortal.isAttached) {
      setTimeout(() => {
        this._tooltipRef = this._overlayRef?.attach(this._tooltipPortal);
      }, 500);
    }
  }

  @HostListener('mouseleave')
  hide(): void {
    if (this._overlayRef) {
      this._overlayRef.detach();
    }
  }

  ngOnDestroy(): void {
    if (this._overlayRef) {
      this._overlayRef.dispose();
    }
  }
balmy yew
#

for each mouseenter, it will try to attach since it's not attached yet

#
 if (!this._tooltipPortal.isAttached) {
      setTimeout(() => {
        if (!this._tooltipPortal.isAttached) { // Check again?
          this._tooltipRef = this._overlayRef?.attach(this._tooltipPortal);
        }
      }, 500);
    }
#

or use attaching property

#

which you set to true before you run setTimeout

#
private _overlayRef: OverlayRef | undefined;
private _tooltipRef: ComponentRef<TooltipContainerComponent> | undefined;
private _tooltipPortal: ComponentPortal<TooltipContainerComponent> = new ComponentPortal(TooltipContainerComponent);
private attaching = false;

@HostListener('mouseenter')
  show(): void {
    if (!this._overlayRef) {
      return;
    }

    // Check if it is already attached
    if (!this._tooltipPortal.isAttached && !this.attaching) {
      this.attaching = true;
      setTimeout(() => {
        this.attaching = false;
        this._tooltipRef = this._overlayRef?.attach(this._tooltipPortal);
      }, 500);
    }
  }

  @HostListener('mouseleave')
  hide(): void {
    if (this._overlayRef) {
      this._overlayRef.detach();
    }
  }

  ngOnDestroy(): void {
    if (this._overlayRef) {
      this._overlayRef.dispose();
    }
  }
brisk sparrow
#

Thanks, great idea