fix(menu): wrong offset for nested menu in a fallback position (#7562)

* Adds the ability to set offsets on connected position fallbacks.
* Fixes wrong positioning of nested menu if they're in a fallback position.

Fixes #7549.
This commit is contained in:
Kristiyan Kostadinov
2017-10-12 22:48:07 +02:00
committed by Andrew Seguin
parent f0f6a7468f
commit 074f6cea62
4 changed files with 44 additions and 10 deletions
@@ -326,6 +326,28 @@ describe('ConnectedPositionStrategy', () => {
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left));
});
it('should allow for the fallback positions to specify their own offsets', () => {
originElement.style.bottom = '0';
originRect = originElement.getBoundingClientRect();
strategy = positionBuilder
.connectedTo(
fakeElementRef,
{originX: 'start', originY: 'top'},
{overlayX: 'start', overlayY: 'top'})
.withFallbackPosition(
{originX: 'start', originY: 'top'},
{overlayX: 'start', overlayY: 'bottom'},
-100, -100);
strategy.withOffsetY(50).withOffsetY(50);
strategy.attach(fakeOverlayRef(overlayElement));
strategy.apply();
let overlayRect = overlayElement.getBoundingClientRect();
expect(Math.floor(overlayRect.bottom)).toBe(Math.floor(originRect.top - 100));
expect(Math.floor(overlayRect.left)).toBe(Math.floor(originRect.left - 100));
});
});
it('should emit onPositionChange event when position changes', () => {
@@ -192,8 +192,12 @@ export class ConnectedPositionStrategy implements PositionStrategy {
*/
withFallbackPosition(
originPos: OriginConnectionPosition,
overlayPos: OverlayConnectionPosition): this {
this._preferredPositions.push(new ConnectionPositionPair(originPos, overlayPos));
overlayPos: OverlayConnectionPosition,
offsetX?: number,
offsetY?: number): this {
const position = new ConnectionPositionPair(originPos, overlayPos, offsetX, offsetY);
this._preferredPositions.push(position);
return this;
}
@@ -296,9 +300,13 @@ export class ConnectedPositionStrategy implements PositionStrategy {
overlayStartY = pos.overlayY == 'top' ? 0 : -overlayRect.height;
}
// The (x, y) offsets of the overlay based on the current position.
let offsetX = typeof pos.offsetX === 'undefined' ? this._offsetX : pos.offsetX;
let offsetY = typeof pos.offsetY === 'undefined' ? this._offsetY : pos.offsetY;
// The (x, y) coordinates of the overlay.
let x = originPoint.x + overlayStartX + this._offsetX;
let y = originPoint.y + overlayStartY + this._offsetY;
let x = originPoint.x + overlayStartX + offsetX;
let y = originPoint.y + overlayStartY + offsetY;
// How much the overlay would overflow at this position, on each side.
let leftOverflow = 0 - x;
@@ -33,7 +33,12 @@ export class ConnectionPositionPair {
overlayX: HorizontalConnectionPos;
overlayY: VerticalConnectionPos;
constructor(origin: OriginConnectionPosition, overlay: OverlayConnectionPosition) {
constructor(
origin: OriginConnectionPosition,
overlay: OverlayConnectionPosition,
public offsetX?: number,
public offsetY?: number) {
this.originX = origin.originX;
this.originY = origin.originY;
this.overlayX = overlay.overlayX;
+4 -5
View File
@@ -354,9 +354,6 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
// to the edges of the trigger, instead of overlapping it.
overlayFallbackX = originX = this.menu.xPosition === 'before' ? 'start' : 'end';
originFallbackX = overlayX = originX === 'end' ? 'start' : 'end';
// TODO(crisbeto): this should be a function, once the overlay supports it.
// Right now it will be wrong for the fallback positions.
offsetY = overlayY === 'bottom' ? MENU_PANEL_TOP_PADDING : -MENU_PANEL_TOP_PADDING;
} else if (!this.menu.overlapTrigger) {
originY = overlayY === 'top' ? 'bottom' : 'top';
@@ -372,10 +369,12 @@ export class MatMenuTrigger implements AfterContentInit, OnDestroy {
{overlayX: overlayFallbackX, overlayY})
.withFallbackPosition(
{originX, originY: originFallbackY},
{overlayX, overlayY: overlayFallbackY})
{overlayX, overlayY: overlayFallbackY},
undefined, -offsetY)
.withFallbackPosition(
{originX: originFallbackX, originY: originFallbackY},
{overlayX: overlayFallbackX, overlayY: overlayFallbackY});
{overlayX: overlayFallbackX, overlayY: overlayFallbackY},
undefined, -offsetY);
}
/** Cleans up the active subscriptions. */