Description
Reproduction
Note: It's probably easier to look at the code than trying to reproduce, see "Actual Behavior".
I am using the cdk overlay to display a context menu flexibly connected to a panel element at a given position (offsetX, offsetY) relative to the panel's top/left. Basically works but only when the overlay fits into the viewport at the given offset.
Steps to reproduce:
- Use a large overlay with FlexibleConnectedPositionStrategy and a position with large offsetX and offsetY, and start/top for originX/Y and overlayX/Y.
- Open the overlay at an offset so its bottom part is outside the viewport.
Expected Behavior
I would expect the overlay to be pushed into the viewport so it is completely visible (if enough space).
Actual Behavior
The overlay is not pushed into the viewport.
I debugged it and the problem is that FlexibleConnectedPositionStrategy _pushOverlayOnScreen() does not take the offset into account, it only checks if the overlay would fit into the viewport without applying the offset. That's the bug in my understanding.
On the other hand, in the preceding code in apply(), that picks the best position (the "fallback"), the offset is taken into account, but that only checks if the overlay's preferred positions fit the viewport, it does not adjust the position / "push" the overlay.
A simple solution would be to add the offset to the overlayPoint before calling _pushOverlayOnScreen(), and to substract it again afterwards, since the offset is applied later via the CSS transform. So, something like this in _getExactOverlayY (and likewise in _getExactOverlayX for offsetX)
_getExactOverlayY(...) {
....
if (this._isPushed) {
if (position.offsetY) overlayPoint.y += position.offsetY;
overlayPoint = this._pushOverlayOnScreen(overlayPoint, this._overlayRect, scrollPosition);
if (position.offsetY) overlayPoint.y -= position.offsetY;
}
....
}
Environment
- Angular: 12.2.1
- CDK/Material: 12.2.1
- Browser(s): All
- Operating System (e.g. Windows, macOS, Ubuntu): All