title: How to keep Angular CDK Overlay component within page based on page offset
body: <p>I am working on my library <a href="https://github.com/kayvanbree/contexr" rel="nofollow noreferrer">Contexr</a>. I just refactored my application to use the Angular CDK Overlay to display the context menu, so I don't have to include some component in the actual application anymore (one less installation-step). </p>
  
  <p>I once used the <a href="https://github.com/angular/material2/blob/master/src/cdk/overlay/position/flexible-connected-position-strategy.ts" rel="nofollow noreferrer">FlexibleConnectedPositionStrategy</a> to create a dropdown beneath an element, which would keep within the page. This position strategy is created like using an ElementRef:</p>
  
  <pre><code>const positionStrategy = this.overlay.position()
        .flexibleConnectedTo(elementRef)
        .left(state.left + 'px')
        .top(state.top + 'px');
  </code></pre>
  
  <p>The problem is that I don't have an ElementRef to go from. My overlay should be flexible connected to my .left() and .top(). Is there a way to do this with the FlexibleConnectedPositionStrategy? Currently I'm trying to use the GlobalPositionStrategy, but that doesn't account for elements going off-screen. </p>
  
  <p><strong>The class that opens the overlay:</strong></p>
  
  <pre><code>@Injectable({
    providedIn: 'root'
  })
  export class ContextMenuService {
    private overlayRef: OverlayRef;
  
    constructor(private overlay: Overlay, private injector: Injector) {}
  
    public open(state: ContextState) {
      const overlayConfig = this.getOverlayConfig(state);
      this.overlayRef = this.overlay.create(overlayConfig);
      const contextMenuRef = new ContextMenuOverlayRef(this.overlayRef);
      this.attachDialogContainer(this.overlayRef, state, contextMenuRef);
    }
  
    private getOverlayConfig(state: ContextState) {
      const positionStrategy = this.overlay.position()
        .global()
        .left(state.left + 'px')
        .top(state.top + 'px');
  
      return {
        positionStrategy: positionStrategy
      };
    }
  
    private createInjector(state: ContextState, dialogRef: ContextMenuOverlayRef) {
      const injectionTokens = new WeakMap();
      injectionTokens.set(ContextMenuOverlayRef, dialogRef);
      injectionTokens.set(CONTEXT_MENU_OVERLAY_DATA, state);
      return new PortalInjector(this.injector, injectionTokens);
    }
  
    private attachDialogContainer(overlayRef: OverlayRef, state: ContextState, contextMenuOverlayRef: ContextMenuOverlayRef) {
      const injector = this.createInjector(state, contextMenuOverlayRef);
      const containerPortal = new ComponentPortal(ContextMenuComponent, null, injector);
      overlayRef.attach(containerPortal);
    }
  
    public close() {
      if (this.overlayRef) {
        this.overlayRef.dispose();
      }
    }
  }
  </code></pre>