From 7fe967e4913233535736d83346f2d1be793a6ed3 Mon Sep 17 00:00:00 2001 From: crisbeto Date: Sat, 2 Nov 2019 13:26:55 +0100 Subject: [PATCH] fix(overlay): maxWidth and maxHeight not applied when using exact dimensions Usually the `maxWidth` and `maxHeight` are applied to the connected overlay's bounding box, because it's the one that determines the dimensions and the overlay pane stretches to fill them. In the case where exact dimensions are used, we make the bounding box the size of the viewport and we let the overlay grow on its own, however we weren't re-applying the `maxWidth` and `maxHeight`. Fixes #17582. --- ...exible-connected-position-strategy.spec.ts | 59 +++++++++++++++++++ .../flexible-connected-position-strategy.ts | 25 ++++++-- 2 files changed, 78 insertions(+), 6 deletions(-) diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts index 5ec91669aba1..89b2dab4d1ba 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.spec.ts @@ -2019,6 +2019,65 @@ describe('FlexibleConnectedPositionStrategy', () => { document.body.removeChild(veryLargeElement); }); + it('should set the maxWidth and maxHeight on the bounding box when exact dimension are ' + + 'not used', () => { + originElement.style.top = '50px'; + originElement.style.left = '50%'; + originElement.style.position = 'fixed'; + + positionStrategy + .withFlexibleDimensions() + .withPositions([{ + overlayX: 'start', + overlayY: 'top', + originX: 'start', + originY: 'bottom' + }]); + + attachOverlay({ + positionStrategy, + maxWidth: 250, + maxHeight: 300 + }); + + const overlayStyle = overlayRef.overlayElement.style; + const boundingBoxStyle = overlayRef.hostElement.style; + + expect(overlayStyle.maxWidth).toBeFalsy(); + expect(overlayStyle.maxHeight).toBeFalsy(); + expect(boundingBoxStyle.maxWidth).toBe('250px'); + expect(boundingBoxStyle.maxHeight).toBe('300px'); + }); + + it('should set the maxWidth and maxHeight on the overlay pane when exact dimensions are used', + () => { + originElement.style.bottom = '0'; + originElement.style.left = '50%'; + originElement.style.position = 'fixed'; + + positionStrategy + .withFlexibleDimensions() + .withPositions([{ + overlayX: 'start', + overlayY: 'top', + originX: 'start', + originY: 'bottom' + }]); + + attachOverlay({ + positionStrategy, + maxWidth: 250, + maxHeight: 300 + }); + + const overlayStyle = overlayRef.overlayElement.style; + const boundingBoxStyle = overlayRef.hostElement.style; + + expect(overlayStyle.maxWidth).toBe('250px'); + expect(overlayStyle.maxHeight).toBe('300px'); + expect(boundingBoxStyle.maxWidth).toBeFalsy(); + expect(boundingBoxStyle.maxHeight).toBeFalsy(); + }); }); diff --git a/src/cdk/overlay/position/flexible-connected-position-strategy.ts b/src/cdk/overlay/position/flexible-connected-position-strategy.ts index 36111025d42d..8f748de9a613 100644 --- a/src/cdk/overlay/position/flexible-connected-position-strategy.ts +++ b/src/cdk/overlay/position/flexible-connected-position-strategy.ts @@ -791,7 +791,7 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { if (this._hasExactPosition()) { styles.top = styles.left = '0'; - styles.bottom = styles.right = ''; + styles.bottom = styles.right = styles.maxHeight = styles.maxWidth = ''; styles.width = styles.height = '100%'; } else { const maxHeight = this._overlayRef.getConfig().maxHeight; @@ -860,8 +860,11 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { /** Sets positioning styles to the overlay element. */ private _setOverlayElementStyles(originPoint: Point, position: ConnectedPosition): void { const styles = {} as CSSStyleDeclaration; + const hasExactPosition = this._hasExactPosition(); + const hasFlexibleDimensions = this._hasFlexibleDimensions; + const config = this._overlayRef.getConfig(); - if (this._hasExactPosition()) { + if (hasExactPosition) { const scrollPosition = this._viewportRuler.getViewportScrollPosition(); extendStyles(styles, this._getExactOverlayY(position, originPoint, scrollPosition)); extendStyles(styles, this._getExactOverlayX(position, originPoint, scrollPosition)); @@ -891,12 +894,22 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy { // If a maxWidth or maxHeight is specified on the overlay, we remove them. We do this because // we need these values to both be set to "100%" for the automatic flexible sizing to work. // The maxHeight and maxWidth are set on the boundingBox in order to enforce the constraint. - if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxHeight) { - styles.maxHeight = ''; + // Note that this doesn't apply when we have an exact position, in which case we do want to + // apply them because they'll be cleared from the bounding box. + if (config.maxHeight) { + if (hasExactPosition) { + styles.maxHeight = coerceCssPixelValue(config.maxHeight); + } else if (hasFlexibleDimensions) { + styles.maxHeight = ''; + } } - if (this._hasFlexibleDimensions && this._overlayRef.getConfig().maxWidth) { - styles.maxWidth = ''; + if (config.maxWidth) { + if (hasExactPosition) { + styles.maxWidth = coerceCssPixelValue(config.maxWidth); + } else if (hasFlexibleDimensions) { + styles.maxWidth = ''; + } } extendStyles(this._pane.style, styles);