Andrei V
Andrei V

Reputation: 1538

Angular CDK Overlay: how to calculate projected content height/width

I'm using Angular CDK Overlay. One of the properties in config is FlexibleConnectedPositionStrategy. Im trying to attach overlay on top of my click trigger. All is working fine when there is enough space on top to fit overlay. What Id like to do is check if there is not enough space at the top then attach overlay to the bottom of the trigger. To do that I need some way after calling Overlay.open(...) to get access to projected content so i can calculate it's dimensions. Is there way to do that?

So far I only see hackish way to access internal _projectedViews[] array but its undocumented feature. Trying to find cleaner way.

Upvotes: 0

Views: 3586

Answers (1)

Eliseo
Eliseo

Reputation: 57971

Andrei, when you define the cdk-overly you choose the "positionStrategy". The order of the positions is defined in the array withPositions. You can see this link (I don't know if is a bit outdated or not): netanet basal cdk overlay (really the Angular material cdk-overlay is very poor), that I try to simply in this SO

Normally you import the overlay and the overlayPositionBuilder

constructor(public overlay: Overlay)

You create the overLayRef using create

const overlayRef = overlay.create();

The function create is an object of type OverlayConfig with properties: Height, width, maxWidth,.. and (among others) positionStrategy, that is an object of type PositionStrategy

So first you create an object of type PositionStrategy. For this you can use the the method position() of overlay

This object has the method flexibleConnectedTo

You can choose "connected" to ElementRef | HTMLElement| Point & { width?: number; height?: number;};

this return a FlexibleConnectedPositionStrategy that you can give value to positions (an array of ConnectionPositionPair), or directy or using the method withPositions

so, e.g.

const positionStrategy = this.overlayPositionBuilder
      .flexibleConnectedTo({ x, y })
      .withPositions([{
        originX: 'center',
        originY: 'top',
        overlayX: 'center',
        overlayY: 'bottom',
      },
      {
        originX: 'center',
        originY: 'bottom',
        overlayX: 'center',
        overlayY: 'top',
      }]);

make that try first attach to top, but if there're no enough space use the second defined position

Update

Well, de final position can be get enclosed in a setTimeout() after execute the attach, e.g.

   //After attach
   this.overlayRef.attach(new TemplatePortal(menu, viewContainerRef, {
            $implicit: data, close:this.close
        }));
    //enclosed in a setTimeout() we has this.overlayRef.overlayElement
    setTimeout(()=>{
      console.log(this.overlayRef.overlayElement.getBoundingClientRect())
    })

Upvotes: 3

Related Questions