How do I add a position strategy to an Angular CDK overlay?
Asked Answered
S

2

19

How do I add a positioning strategy (ConnectedPositionStrategy) to an Angular CDK overlay?

I've tried specifying it via the positionStrategy property and passed it into overlay.create().

import { Overlay, ConnectedPositionStrategy } from '@angular/cdk/overlay';
// ...
export class MyComponent {
    constructor(private overlay: Overlay){}
    showOverlay() {
        let overlay = this.overlay.create({positionStrategy: ConnectedPositionStrategy});
        // ...
    }
}

But I get this error:

ERROR in src/app/explore/explore.component.ts(48,40): error TS2345: Argument of type '{ positionStrategy: typeof ConnectedPositionStrategy; }' is not assignable to parameter of type 'OverlayConfig'.
  Types of property 'positionStrategy' are incompatible.
    Type 'typeof ConnectedPositionStrategy' is not assignable to type 'PositionStrategy'.
      Property 'attach' is missing in type 'typeof ConnectedPositionStrategy'.

Am I missing something? The docs aren't very clear about how to specify a positioning strategy.

Here are my dependencies (outputted from ng version):

    _                      _                 ____ _     ___
   / \   _ __   __ _ _   _| | __ _ _ __     / ___| |   |_ _|
  / △ \ | '_ \ / _` | | | | |/ _` | '__|   | |   | |    | |
 / ___ \| | | | (_| | |_| | | (_| | |      | |___| |___ | |
/_/   \_\_| |_|\__, |\__,_|_|\__,_|_|       \____|_____|___|
               |___/

Angular CLI: 1.6.1
Node: 8.9.0
OS: darwin x64
Angular: 5.1.1
... animations, common, compiler, compiler-cli, core, forms
... platform-browser, platform-browser-dynamic, platform-server
... router, service-worker

@angular/cdk: 5.0.1-2436acd
@angular/cli: 1.6.1
@angular/flex-layout: 2.0.0-beta.12-82ae74c
@angular/material: 5.0.1-2436acd
@angular-devkit/build-optimizer: 0.0.36
@angular-devkit/core: 0.0.22
@angular-devkit/schematics: 0.0.42
@ngtools/json-schema: 1.1.0
@ngtools/webpack: 1.9.1
@schematics/angular: 0.1.11
@schematics/schematics: 0.0.11
typescript: 2.4.2
webpack: 3.10.0

Additionally, I've tried initializing a positionStrategy via the new keyword, but now I've no idea what to pass the arguments as.

Slowworm answered 19/12, 2017 at 8:3 Comment(0)
G
18

there is at least two errors in your example :

1/ the method create exist on class Overlay not (OverlayContainer)

2/ ConnectedPositionStrategy is not an object, its a typescript interface ( that why you get error ... typeof ConnectedPositionStrategy ... )

then the best way to create a "connected" overlay is to use the OverlayPositionBuilder ( here the doc, but this will not help much )

If you scan angular material repo you will see some example, like in the datepicker who use :

            .connectedTo(this._datepickerInput.getPopupConnectionElementRef(), { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })

so you can certainly use this snippet by replacing this._datepickerInput.getPopupConnectionElementRef() by your component elementRef

 constructor (
 ...
 private overlay: Overlay
 ) {}

showOverlay() {
    let overlay = this.overlay.create({
        positionStrategy: this.overlay.position().connectedTo(<yourElRef>, { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })
    });
 }
Gaslight answered 19/12, 2017 at 8:47 Comment(2)
Oops.. I meant Overlay. Updating the question.Slowworm
Can you Please provide an updated solution as connectedTo() is showing the Deprecation flag so I want to use flexibleConnectedTo()Evanevander
E
22

After some search including this post. I have come with an updated solution for the use of cdk overlay for menus and others with the conected position strategy. (using flexible since conected show deprecated decoration)

const positionStrategy = this.overlay.position()
      .flexibleConnectedTo(elementRef)
      .withPositions([{
        originX: 'start',
        originY: 'bottom',
        overlayX: 'start',
        overlayY: 'top',
      }, {
        originX: 'start',
        originY: 'top',
        overlayX: 'start',
        overlayY: 'bottom',
      }]);

Then add a scroll strategy for your needs, for example reposition in case you want your menu to reposition on scroll

scrollStrategy: this.overlay.scrollStrategies.reposition()

But if your scroll is not on the main body, you need to add the cdk-scrollable directive from

import {ScrollingModule} from '@angular/cdk/scrolling';

to

<div class="your-scroll-container" cdk-scrollable>
Exfoliation answered 7/11, 2019 at 12:8 Comment(1)
Thanks Jorge, very useful, now I have to figure how to set everything in place and possibly move the overlay above the origin if it's close to the bottom of the page... But this is great alreadyPorthole
G
18

there is at least two errors in your example :

1/ the method create exist on class Overlay not (OverlayContainer)

2/ ConnectedPositionStrategy is not an object, its a typescript interface ( that why you get error ... typeof ConnectedPositionStrategy ... )

then the best way to create a "connected" overlay is to use the OverlayPositionBuilder ( here the doc, but this will not help much )

If you scan angular material repo you will see some example, like in the datepicker who use :

            .connectedTo(this._datepickerInput.getPopupConnectionElementRef(), { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })

so you can certainly use this snippet by replacing this._datepickerInput.getPopupConnectionElementRef() by your component elementRef

 constructor (
 ...
 private overlay: Overlay
 ) {}

showOverlay() {
    let overlay = this.overlay.create({
        positionStrategy: this.overlay.position().connectedTo(<yourElRef>, { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })
    });
 }
Gaslight answered 19/12, 2017 at 8:47 Comment(2)
Oops.. I meant Overlay. Updating the question.Slowworm
Can you Please provide an updated solution as connectedTo() is showing the Deprecation flag so I want to use flexibleConnectedTo()Evanevander

© 2022 - 2024 — McMap. All rights reserved.