Search code examples
angularangular-materialoverlayangular-cdk

Material CDK Overlay flexibleConnectedTo doesn't accept Angular component as origin


I have an Angular component, which is actually a button under the hood :

<app-button (click)="showText(thebutton)" #thebutton>
    <button type="button" class=""><span>Popover</span></button>
</app-button>

showText() method calls the PopoverService.open() method, which should display a popover (tooltip) next to the button.

Problem is, the popover appears on the upper-left corner of the browser window and not next to the element.

<div id="cdk-overlay-0" class="cdk-overlay-pane" style="pointer-events: auto;">
    <app-popover>
        <div class="popover"></div>
    </app-popover>
</div>

app-button has a "display: inline-block; position: relative;" style, just like an ordinary html button.

When I change the code to an ordinary HTML button, it works as expected :

<button (click)="showText(thebutton)" #thebutton>Popover</button>

and Material CDK adds a "top" and "left" style as seen below:

<div id="cdk-overlay-2" class="cdk-overlay-pane" style="pointer-events: auto; top: 87px; left: 389.656px;">
    <app-popover>
        <div class="popover"></div>
    </app-popover>
</div>

A simple div with style "display: inline-block" works as well.

Why wouldn't an Angular component (with style "display: inline-block; position: relative;") not work and how can I make it work?


Solution

  • Solved it by adding ".elementRef" to the component :

    <app-button (click)="showText(thebutton.elementRef)" #thebutton>
        <button type="button" class=""><span>Popover</span></button>
    </app-button>
    

    From the Angular Material CDK source code here

    /** Possible values that can be set as the origin of a FlexibleConnectedPositionStrategy. */
    export type FlexibleConnectedPositionStrategyOrigin = ElementRef | HTMLElement | Point & {
      width?: number;
      height?: number;
    };
    

    So the parameter 'origin' passed to the Angular CDK Overlay service has to be of type "ElementRef | HTMLElement" (or Point, which is { readonly x: number; readonly y: number; }).

    I leave this here, hope this helps someone in future.