Skip to content

refactor(overlay): move connected position assertions into FlexibleConnectedPositionStrategy #10464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 0 additions & 57 deletions src/cdk/overlay/position/connected-position-strategy.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ const DEFAULT_WIDTH = 60;
describe('ConnectedPositionStrategy', () => {
let overlay: Overlay;
let overlayContainer: OverlayContainer;
let overlayContainerElement: HTMLElement;
let zone: MockNgZone;
let overlayRef: OverlayRef;

Expand All @@ -39,7 +38,6 @@ describe('ConnectedPositionStrategy', () => {
inject([Overlay, OverlayContainer], (o: Overlay, oc: OverlayContainer) => {
overlay = o;
overlayContainer = oc;
overlayContainerElement = oc.getContainerElement();
})();
});

Expand Down Expand Up @@ -775,61 +773,6 @@ describe('ConnectedPositionStrategy', () => {

});

describe('validations', () => {
let overlayElement: HTMLElement;
let originElement: HTMLElement;
let positionStrategy: ConnectedPositionStrategy;

beforeEach(() => {
overlayElement = createPositionedBlockElement();
overlayContainerElement.appendChild(overlayElement);
originElement = createBlockElement();

positionStrategy = overlay.position().connectedTo(
new ElementRef(originElement),
{originX: 'start', originY: 'bottom'},
{overlayX: 'start', overlayY: 'top'});

attachOverlay(positionStrategy);
});

afterEach(() => {
positionStrategy.dispose();
});

it('should throw when attaching without any positions', () => {
positionStrategy.withPositions([]);
expect(() => positionStrategy.apply()).toThrow();
});

it('should throw when passing in something that is missing a connection point', () => {
positionStrategy.withPositions([{originY: 'top', overlayX: 'start', overlayY: 'top'} as any]);
expect(() => positionStrategy.apply()).toThrow();
});

it('should throw when passing in something that has an invalid X position', () => {
positionStrategy.withPositions([{
originX: 'left',
originY: 'top',
overlayX: 'left',
overlayY: 'top'
} as any]);

expect(() => positionStrategy.apply()).toThrow();
});

it('should throw when passing in something that has an invalid Y position', () => {
positionStrategy.withPositions([{
originX: 'start',
originY: 'middle',
overlayX: 'start',
overlayY: 'middle'
} as any]);

expect(() => positionStrategy.apply()).toThrow();
});
});

});

/** Creates an absolutely positioned, display: block element with a default size. */
Expand Down
21 changes: 0 additions & 21 deletions src/cdk/overlay/position/connected-position-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,6 @@ import {
ConnectionPositionPair,
OriginConnectionPosition,
OverlayConnectionPosition,
validateHorizontalPosition,
validateVerticalPosition,
} from './connected-position';
import {FlexibleConnectedPositionStrategy} from './flexible-connected-position-strategy';
import {PositionStrategy} from './position-strategy';
Expand Down Expand Up @@ -109,7 +107,6 @@ export class ConnectedPositionStrategy implements PositionStrategy {
* @docs-private
*/
apply(): void {
this._validatePositions();
this._positionStrategy.apply();
}

Expand All @@ -119,7 +116,6 @@ export class ConnectedPositionStrategy implements PositionStrategy {
* allows one to re-align the panel without changing the orientation of the panel.
*/
recalculateLastPosition(): void {
this._validatePositions();
this._positionStrategy.reapplyLastPosition();
}

Expand Down Expand Up @@ -213,21 +209,4 @@ export class ConnectedPositionStrategy implements PositionStrategy {
this._positionStrategy.setOrigin(origin);
return this;
}

/** Validates that the current position match the expected values. */
private _validatePositions(): void {
if (!this._preferredPositions.length) {
throw Error('ConnectedPositionStrategy: At least one position is required.');
}

// TODO(crisbeto): remove these once Angular's template type
// checking is advanced enough to catch these cases.
// TODO(crisbeto): port these checks into the flexible positioning.
this._preferredPositions.forEach(pair => {
validateHorizontalPosition('originX', pair.originX);
validateVerticalPosition('originY', pair.originY);
validateHorizontalPosition('overlayX', pair.overlayX);
validateVerticalPosition('overlayY', pair.overlayY);
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1593,6 +1593,57 @@ describe('FlexibleConnectedPositionStrategy', () => {

});

describe('validations', () => {
let originElement: HTMLElement;
let positionStrategy: FlexibleConnectedPositionStrategy;

beforeEach(() => {
originElement = createPositionedBlockElement();
document.body.appendChild(originElement);
positionStrategy = overlay.position().flexibleConnectedTo(new ElementRef(originElement));
});

afterEach(() => {
positionStrategy.dispose();
});

it('should throw when attaching without any positions', () => {
expect(() => positionStrategy.withPositions([])).toThrow();
});

it('should throw when passing in something that is missing a connection point', () => {
expect(() => {
positionStrategy.withPositions([{
originY: 'top',
overlayX: 'start',
overlayY: 'top'
} as any]);
}).toThrow();
});

it('should throw when passing in something that has an invalid X position', () => {
expect(() => {
positionStrategy.withPositions([{
originX: 'left',
originY: 'top',
overlayX: 'left',
overlayY: 'top'
} as any]);
}).toThrow();
});

it('should throw when passing in something that has an invalid Y position', () => {
expect(() => {
positionStrategy.withPositions([{
originX: 'start',
originY: 'middle',
overlayX: 'start',
overlayY: 'middle'
} as any]);
}).toThrow();
});
});

});

/** Creates an absolutely positioned, display: block element with a default size. */
Expand Down
22 changes: 22 additions & 0 deletions src/cdk/overlay/position/flexible-connected-position-strategy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ import {
ConnectedOverlayPositionChange,
ConnectionPositionPair,
ScrollingVisibility,
validateHorizontalPosition,
validateVerticalPosition,
} from './connected-position';
import {Observable, Subscription, Subject} from 'rxjs';
import {OverlayRef} from '../overlay-ref';
Expand Down Expand Up @@ -127,6 +129,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
throw Error('This position strategy is already attached to an overlay');
}

this._validatePositions();

overlayRef.hostElement.classList.add('cdk-overlay-connected-position-bounding-box');

this._overlayRef = overlayRef;
Expand Down Expand Up @@ -315,6 +319,8 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {
this._lastPosition = null;
}

this._validatePositions();

return this;
}

Expand Down Expand Up @@ -901,6 +907,22 @@ export class FlexibleConnectedPositionStrategy implements PositionStrategy {

return position.offsetY == null ? this._offsetY : position.offsetY;
}

/** Validates that the current position match the expected values. */
private _validatePositions(): void {
if (!this._preferredPositions.length) {
throw Error('FlexibleConnectedPositionStrategy: At least one position is required.');
}

// TODO(crisbeto): remove these once Angular's template type
// checking is advanced enough to catch these cases.
this._preferredPositions.forEach(pair => {
validateHorizontalPosition('originX', pair.originX);
validateVerticalPosition('originY', pair.originY);
validateHorizontalPosition('overlayX', pair.overlayX);
validateVerticalPosition('overlayY', pair.overlayY);
});
}
}

/** A simple (x, y) coordinate. */
Expand Down