refactor(overlay): allow for object to be passed to the OverlayState constructor (#6615)

Allows for a config object to be passed to the `OverlayState` constructor. This makes the longer configurations a bit more convenient to use.
This commit is contained in:
Kristiyan Kostadinov
2017-09-01 17:07:35 +02:00
committed by Jeremy Elbourn
parent 21c68ad95e
commit fe37cb2551
15 changed files with 95 additions and 87 deletions
+6 -7
View File
@@ -272,7 +272,12 @@ export class ConnectedOverlayDirective implements OnDestroy, OnChanges {
/** Builds the overlay config based on the directive's inputs */
private _buildConfig(): OverlayState {
let overlayConfig = new OverlayState();
const positionStrategy = this._position = this._createPositionStrategy();
const overlayConfig = new OverlayState({
positionStrategy,
scrollStrategy: this.scrollStrategy,
hasBackdrop: this.hasBackdrop
});
if (this.width || this.width === 0) {
overlayConfig.width = this.width;
@@ -290,16 +295,10 @@ export class ConnectedOverlayDirective implements OnDestroy, OnChanges {
overlayConfig.minHeight = this.minHeight;
}
overlayConfig.hasBackdrop = this.hasBackdrop;
if (this.backdropClass) {
overlayConfig.backdropClass = this.backdropClass;
}
this._position = this._createPositionStrategy() as ConnectedPositionStrategy;
overlayConfig.positionStrategy = this._position;
overlayConfig.scrollStrategy = this.scrollStrategy;
return overlayConfig;
}
+15 -4
View File
@@ -29,7 +29,9 @@ export class OverlayRef implements PortalHost {
private _state: OverlayState,
private _ngZone: NgZone) {
_state.scrollStrategy.attach(this);
if (_state.scrollStrategy) {
_state.scrollStrategy.attach(this);
}
}
/** The overlay's HTML element */
@@ -54,7 +56,10 @@ export class OverlayRef implements PortalHost {
this.updateSize();
this.updateDirection();
this.updatePosition();
this._state.scrollStrategy.enable();
if (this._state.scrollStrategy) {
this._state.scrollStrategy.enable();
}
// Enable pointer events for the overlay pane element.
this._togglePointerEvents(true);
@@ -89,7 +94,10 @@ export class OverlayRef implements PortalHost {
// This is necessary because otherwise the pane element will cover the page and disable
// pointer events therefore. Depends on the position strategy and the applied pane boundaries.
this._togglePointerEvents(false);
this._state.scrollStrategy.disable();
if (this._state.scrollStrategy) {
this._state.scrollStrategy.disable();
}
let detachmentResult = this._portalHost.detach();
@@ -107,7 +115,10 @@ export class OverlayRef implements PortalHost {
this._state.positionStrategy.dispose();
}
this._state.scrollStrategy.disable();
if (this._state.scrollStrategy) {
this._state.scrollStrategy.disable();
}
this.detachBackdrop();
this._portalHost.dispose();
this._attachments.complete();
+8 -2
View File
@@ -18,10 +18,10 @@ import {NoopScrollStrategy} from './scroll/noop-scroll-strategy';
*/
export class OverlayState {
/** Strategy with which to position the overlay. */
positionStrategy: PositionStrategy;
positionStrategy?: PositionStrategy;
/** Strategy to be used when handling scroll events while the overlay is open. */
scrollStrategy: ScrollStrategy = new NoopScrollStrategy();
scrollStrategy?: ScrollStrategy = new NoopScrollStrategy();
/** Custom class to add to the overlay pane. */
panelClass?: string | string[] = '';
@@ -53,6 +53,12 @@ export class OverlayState {
/** The direction of the text in the overlay panel. */
direction?: Direction = 'ltr';
constructor(state?: OverlayState) {
if (state) {
Object.keys(state).forEach(key => this[key] = state[key]);
}
}
// TODO(jelbourn): configuration still to add
// - focus trap
// - disable pointer events
+6 -12
View File
@@ -133,8 +133,7 @@ describe('Overlay', () => {
});
it('should set the direction', () => {
const state = new OverlayState();
state.direction = 'rtl';
const state = new OverlayState({direction: 'rtl'});
overlay.create(state).attach(componentPortal);
@@ -153,10 +152,7 @@ describe('Overlay', () => {
});
it('should emit the attachment event after everything is added to the DOM', () => {
let state = new OverlayState();
state.hasBackdrop = true;
let state = new OverlayState({hasBackdrop: true});
let overlayRef = overlay.create(state);
overlayRef.attachments().subscribe(() => {
@@ -415,9 +411,8 @@ describe('Overlay', () => {
describe('panelClass', () => {
it('should apply a custom overlay pane class', () => {
const config = new OverlayState();
const config = new OverlayState({panelClass: 'custom-panel-class'});
config.panelClass = 'custom-panel-class';
overlay.create(config).attach(componentPortal);
viewContainerFixture.detectChanges();
@@ -426,9 +421,8 @@ describe('Overlay', () => {
});
it('should be able to apply multiple classes', () => {
const config = new OverlayState();
const config = new OverlayState({panelClass: ['custom-class-one', 'custom-class-two']});
config.panelClass = ['custom-class-one', 'custom-class-two'];
overlay.create(config).attach(componentPortal);
viewContainerFixture.detectChanges();
@@ -445,8 +439,8 @@ describe('Overlay', () => {
let overlayRef: OverlayRef;
beforeEach(() => {
config = new OverlayState();
fakeScrollStrategy = config.scrollStrategy = new FakeScrollStrategy();
fakeScrollStrategy = new FakeScrollStrategy();
config = new OverlayState({scrollStrategy: fakeScrollStrategy});
overlayRef = overlay.create(config);
});
@@ -23,9 +23,8 @@ describe('BlockScrollStrategy', () => {
}));
beforeEach(inject([Overlay, ViewportRuler], (overlay: Overlay, viewportRuler: ViewportRuler) => {
let overlayState = new OverlayState();
let overlayState = new OverlayState({scrollStrategy: overlay.scrollStrategies.block()});
overlayState.scrollStrategy = overlay.scrollStrategies.block();
overlayRef = overlay.create(overlayState);
componentPortal = new ComponentPortal(FocacciaMsg);
@@ -33,8 +33,7 @@ describe('CloseScrollStrategy', () => {
}));
beforeEach(inject([Overlay], (overlay: Overlay) => {
let overlayState = new OverlayState();
overlayState.scrollStrategy = overlay.scrollStrategies.close();
let overlayState = new OverlayState({scrollStrategy: overlay.scrollStrategies.close()});
overlayRef = overlay.create(overlayState);
componentPortal = new ComponentPortal(MozarellaMsg);
}));
@@ -33,8 +33,7 @@ describe('RepositionScrollStrategy', () => {
}));
beforeEach(inject([Overlay], (overlay: Overlay) => {
let overlayState = new OverlayState();
overlayState.scrollStrategy = overlay.scrollStrategies.reposition();
let overlayState = new OverlayState({scrollStrategy: overlay.scrollStrategies.reposition()});
overlayRef = overlay.create(overlayState);
componentPortal = new ComponentPortal(PastaMsg);
}));
+3 -2
View File
@@ -11,9 +11,10 @@ scroll strategy, to the `OverlayState`. By default, all overlays will use the `n
doesn't do anything. The other available strategies are `reposition`, `block` and `close`:
```ts
let overlayState = new OverlayState();
let overlayState = new OverlayState({
scrollStrategy: overlay.scrollStrategies.block()
});
overlayState.scrollStrategy = overlay.scrollStrategies.block();
this._overlay.create(overlayState).attach(yourPortal);
```
+8 -13
View File
@@ -74,10 +74,9 @@ export class OverlayDemo {
{originX: 'start', originY: 'bottom'},
{overlayX: 'start', overlayY: 'top'} );
let config = new OverlayState();
config.positionStrategy = strategy;
let config = new OverlayState({positionStrategy: strategy});
let overlayRef = this.overlay.create(config);
overlayRef.attach(new ComponentPortal(SpagettiPanel, this.viewContainerRef));
}
@@ -88,22 +87,18 @@ export class OverlayDemo {
{originX: 'start', originY: 'bottom'},
{overlayX: 'end', overlayY: 'top'} );
let config = new OverlayState();
config.positionStrategy = strategy;
let config = new OverlayState({positionStrategy: strategy});
let overlayRef = this.overlay.create(config);
overlayRef.attach(this.tortelliniTemplate);
}
openPanelWithBackdrop() {
let config = new OverlayState();
config.positionStrategy = this.overlay.position()
.global()
.centerHorizontally();
config.hasBackdrop = true;
config.backdropClass = 'cdk-overlay-transparent-backdrop';
let config = new OverlayState({
hasBackdrop: true,
backdropClass: 'cdk-overlay-transparent-backdrop',
positionStrategy: this.overlay.position().global().centerHorizontally()
});
let overlayRef = this.overlay.create(config);
overlayRef.attach(this.templatePortals.first);
+6 -6
View File
@@ -468,12 +468,12 @@ export class MdAutocompleteTrigger implements ControlValueAccessor, OnDestroy {
}
private _getOverlayConfig(): OverlayState {
const overlayState = new OverlayState();
overlayState.positionStrategy = this._getOverlayPosition();
overlayState.width = this._getHostWidth();
overlayState.direction = this._dir ? this._dir.value : 'ltr';
overlayState.scrollStrategy = this._scrollStrategy();
return overlayState;
return new OverlayState({
positionStrategy: this._getOverlayPosition(),
scrollStrategy: this._scrollStrategy(),
width: this._getHostWidth(),
direction: this._dir ? this._dir.value : 'ltr'
});
}
private _getOverlayPosition(): PositionStrategy {
+7 -6
View File
@@ -321,12 +321,13 @@ export class MdDatepicker<D> implements OnDestroy {
/** Create the popup. */
private _createPopup(): void {
const overlayState = new OverlayState();
overlayState.positionStrategy = this._createPopupPositionStrategy();
overlayState.hasBackdrop = true;
overlayState.backdropClass = 'md-overlay-transparent-backdrop';
overlayState.direction = this._dir ? this._dir.value : 'ltr';
overlayState.scrollStrategy = this._scrollStrategy();
const overlayState = new OverlayState({
positionStrategy: this._createPopupPositionStrategy(),
hasBackdrop: true,
backdropClass: 'md-overlay-transparent-backdrop',
direction: this._dir ? this._dir.value : 'ltr',
scrollStrategy: this._scrollStrategy()
});
this._popupRef = this._overlay.create(overlayState);
}
+12 -10
View File
@@ -186,17 +186,19 @@ export class MdDialog {
* @returns The overlay configuration.
*/
private _getOverlayState(dialogConfig: MdDialogConfig): OverlayState {
const overlayState = new OverlayState();
overlayState.panelClass = dialogConfig.panelClass;
overlayState.hasBackdrop = dialogConfig.hasBackdrop;
overlayState.scrollStrategy = this._scrollStrategy();
overlayState.direction = dialogConfig.direction;
if (dialogConfig.backdropClass) {
overlayState.backdropClass = dialogConfig.backdropClass;
}
overlayState.positionStrategy = this._overlay.position().global();
const state = new OverlayState({
positionStrategy: this._overlay.position().global(),
scrollStrategy: this._scrollStrategy(),
panelClass: dialogConfig.panelClass,
hasBackdrop: dialogConfig.hasBackdrop,
direction: dialogConfig.direction
});
return overlayState;
if (dialogConfig.backdropClass) {
state.backdropClass = dialogConfig.backdropClass;
}
return state;
}
/**
+7 -7
View File
@@ -322,13 +322,13 @@ export class MdMenuTrigger implements AfterViewInit, OnDestroy {
* @returns OverlayState
*/
private _getOverlayConfig(): OverlayState {
const overlayState = new OverlayState();
overlayState.positionStrategy = this._getPosition();
overlayState.hasBackdrop = !this.triggersSubmenu();
overlayState.backdropClass = 'cdk-overlay-transparent-backdrop';
overlayState.direction = this.dir;
overlayState.scrollStrategy = this._scrollStrategy();
return overlayState;
return new OverlayState({
positionStrategy: this._getPosition(),
hasBackdrop: !this.triggersSubmenu(),
backdropClass: 'cdk-overlay-transparent-backdrop',
direction: this.dir,
scrollStrategy: this._scrollStrategy()
});
}
/**
+5 -3
View File
@@ -153,9 +153,11 @@ export class MdSnackBar {
* @param config The user-specified snack bar config.
*/
private _createOverlay(config: MdSnackBarConfig): OverlayRef {
const state = new OverlayState();
state.direction = config.direction;
state.positionStrategy = this._overlay.position().global().centerHorizontally().bottom('0');
const state = new OverlayState({
direction: config.direction,
positionStrategy: this._overlay.position().global().centerHorizontally().bottom('0')
});
return this._overlay.create(state);
}
+9 -9
View File
@@ -279,13 +279,13 @@ export class MdTooltip implements OnDestroy {
/** Create the overlay config and position strategy */
private _createOverlay(): OverlayRef {
let origin = this._getOrigin();
let position = this._getOverlayPosition();
const origin = this._getOrigin();
const position = this._getOverlayPosition();
// Create connected position strategy that listens for scroll events to reposition.
// After position changes occur and the overlay is clipped by a parent scrollable then
// close the tooltip.
let strategy = this._overlay.position().connectedTo(this._elementRef, origin, position);
const strategy = this._overlay.position().connectedTo(this._elementRef, origin, position);
strategy.withScrollableContainers(this._scrollDispatcher.getScrollContainers(this._elementRef));
strategy.onPositionChange.subscribe(change => {
if (change.scrollableViewProperties.isOverlayClipped &&
@@ -294,12 +294,12 @@ export class MdTooltip implements OnDestroy {
}
});
let config = new OverlayState();
config.direction = this._dir ? this._dir.value : 'ltr';
config.positionStrategy = strategy;
config.panelClass = TOOLTIP_PANEL_CLASS;
config.scrollStrategy = this._scrollStrategy();
const config = new OverlayState({
direction: this._dir ? this._dir.value : 'ltr',
positionStrategy: strategy,
panelClass: TOOLTIP_PANEL_CLASS,
scrollStrategy: this._scrollStrategy()
});
this._overlayRef = this._overlay.create(config);