diff --git a/src/cdk/overlay/overlay-directives.spec.ts b/src/cdk/overlay/overlay-directives.spec.ts index 135e98e4965..0186577e1bc 100644 --- a/src/cdk/overlay/overlay-directives.spec.ts +++ b/src/cdk/overlay/overlay-directives.spec.ts @@ -359,6 +359,42 @@ describe('Overlay directives', () => { expect(Math.floor(overlayRect.left)).toBe(Math.floor(triggerRect.left) + 20); }); + it('should be able to set the viewport margin', () => { + expect(fixture.componentInstance.connectedOverlayDirective.viewportMargin).not.toBe(10); + + fixture.componentInstance.viewportMargin = 10; + fixture.detectChanges(); + + expect(fixture.componentInstance.connectedOverlayDirective.viewportMargin).toBe(10); + }); + + it('should allow for flexible positioning to be enabled', () => { + expect(fixture.componentInstance.connectedOverlayDirective.flexibleDiemsions).not.toBe(true); + + fixture.componentInstance.flexibleDimensions = true; + fixture.detectChanges(); + + expect(fixture.componentInstance.connectedOverlayDirective.flexibleDiemsions).toBe(true); + }); + + it('should allow for growing after open to be enabled', () => { + expect(fixture.componentInstance.connectedOverlayDirective.growAfterOpen).not.toBe(true); + + fixture.componentInstance.growAfterOpen = true; + fixture.detectChanges(); + + expect(fixture.componentInstance.connectedOverlayDirective.growAfterOpen).toBe(true); + }); + + it('should allow for pushing to be enabled', () => { + expect(fixture.componentInstance.connectedOverlayDirective.push).not.toBe(true); + + fixture.componentInstance.push = true; + fixture.detectChanges(); + + expect(fixture.componentInstance.connectedOverlayDirective.push).toBe(true); + }); + }); describe('outputs', () => { @@ -421,6 +457,10 @@ describe('Overlay directives', () => { [cdkConnectedOverlayHeight]="height" [cdkConnectedOverlayOrigin]="triggerOverride || trigger" [cdkConnectedOverlayHasBackdrop]="hasBackdrop" + [cdkConnectedOverlayViewportMargin]="viewportMargin" + [cdkConnectedOverlayFlexibleDimensions]="flexibleDimensions" + [cdkConnectedOverlayGrowAfterOpen]="growAfterOpen" + [cdkConnectedOverlayPush]="push" cdkConnectedOverlayBackdropClass="mat-test-class" (backdropClick)="backdropClickHandler($event)" [cdkConnectedOverlayOffsetX]="offsetX" @@ -448,6 +488,10 @@ class ConnectedOverlayDirectiveTest { offsetY: number; triggerOverride: CdkOverlayOrigin; hasBackdrop: boolean; + viewportMargin: number; + flexibleDimensions: boolean; + growAfterOpen: boolean; + push: boolean; backdropClickHandler = jasmine.createSpy('backdropClick handler'); positionChangeHandler = jasmine.createSpy('positionChangeHandler'); positionOverrides: ConnectionPositionPair[]; diff --git a/src/cdk/overlay/overlay-directives.ts b/src/cdk/overlay/overlay-directives.ts index bdb203b0881..3a9c074fc3d 100644 --- a/src/cdk/overlay/overlay-directives.ts +++ b/src/cdk/overlay/overlay-directives.ts @@ -106,7 +106,8 @@ export class CdkOverlayOrigin { /** - * Directive to facilitate declarative creation of an Overlay using a ConnectedPositionStrategy. + * Directive to facilitate declarative creation of an + * Overlay using a FlexibleConnectedPositionStrategy. */ @Directive({ selector: '[cdk-connected-overlay], [connected-overlay], [cdkConnectedOverlay]', @@ -117,6 +118,9 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { private _templatePortal: TemplatePortal; private _hasBackdrop = false; private _lockPosition = false; + private _growAfterOpen = false; + private _flexibleDimensions = false; + private _push = false; private _backdropSubscription = Subscription.EMPTY; private _offsetX: number; private _offsetY: number; @@ -165,6 +169,9 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { /** The custom class to be set on the backdrop element. */ @Input('cdkConnectedOverlayBackdropClass') backdropClass: string; + /** Margin between the overlay and the viewport edges. */ + @Input('cdkConnectedOverlayViewportMargin') viewportMargin: number = 0; + /** Strategy to be used when handling scroll events while the overlay is open. */ @Input('cdkConnectedOverlayScrollStrategy') scrollStrategy: ScrollStrategy = this._scrollStrategy(); @@ -182,6 +189,21 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { get lockPosition() { return this._lockPosition; } set lockPosition(value: any) { this._lockPosition = coerceBooleanProperty(value); } + /** Whether the overlay's width and height can be constrained to fit within the viewport. */ + @Input('cdkConnectedOverlayFlexibleDimensions') + get flexibleDiemsions() { return this._flexibleDimensions; } + set flexibleDiemsions(value: boolean) { this._flexibleDimensions = coerceBooleanProperty(value); } + + /** Whether the overlay can grow after the initial open when flexible positioning is turned on. */ + @Input('cdkConnectedOverlayGrowAfterOpen') + get growAfterOpen() { return this._growAfterOpen; } + set growAfterOpen(value: boolean) { this._growAfterOpen = coerceBooleanProperty(value); } + + /** Whether the overlay can be pushed on-screen if none of the provided positions fit. */ + @Input('cdkConnectedOverlayPush') + get push() { return this._push; } + set push(value: boolean) { this._push = coerceBooleanProperty(value); } + /** Event emitted when the backdrop is clicked. */ @Output() backdropClick = new EventEmitter(); @@ -288,13 +310,10 @@ export class CdkConnectedOverlay implements OnDestroy, OnChanges { private _createPositionStrategy(): FlexibleConnectedPositionStrategy { const strategy = this._overlay.position() .flexibleConnectedTo(this.origin.elementRef) - // Turn off all of the flexible positioning features for now to have it behave - // the same way as the old ConnectedPositionStrategy and to avoid breaking changes. - // TODO(crisbeto): make these on by default and add inputs for them - // next time we do breaking changes. - .withFlexibleDimensions(false) - .withPush(false) - .withGrowAfterOpen(false) + .withFlexibleDimensions(this.flexibleDiemsions) + .withPush(this.push) + .withGrowAfterOpen(this.growAfterOpen) + .withViewportMargin(this.viewportMargin) .withLockedPosition(this.lockPosition); this._setPositions(strategy); diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.ts index 941bed23865..a793cb568f2 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.ts @@ -137,7 +137,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { overlayRef.hostElement.classList.add('cdk-overlay-connected-position-bounding-box'); this._overlayRef = overlayRef; - this._boundingBox = overlayRef.hostElement!; + this._boundingBox = overlayRef.hostElement; this._pane = overlayRef.overlayElement; this._resizeSubscription.unsubscribe(); this._resizeSubscription = this._viewportRuler.change().subscribe(() => this.apply());