Skip to content

Commit

Permalink
feat(dialog): allow for the dialog dimensions to be updated
Browse files Browse the repository at this point in the history
Adds an `updateDimensions` method to the `MdDialogRef` which allows the user to update a dialog's dimensions after it has been created.

Fixes #2930.
  • Loading branch information
crisbeto committed Feb 5, 2017
1 parent 8d900e0 commit 0c174d2
Show file tree
Hide file tree
Showing 5 changed files with 86 additions and 47 deletions.
27 changes: 22 additions & 5 deletions src/demo-app/dialog/dialog-demo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,32 @@ export class DialogDemo {
@Component({
selector: 'demo-jazz-dialog',
template: `
<p>It's Jazz!</p>
<p><label>How much? <input #howMuch></label></p>
<p> {{ jazzMessage }} </p>
<button type="button" (click)="dialogRef.close(howMuch.value)">Close dialog</button>`
<p>It's Jazz!</p>
<p><label>How much? <input #howMuch></label></p>
<p>{{ jazzMessage }}</p>
<button (click)="dialogRef.close(howMuch.value)">Close dialog</button>
<button (click)="togglePosition()">Change position</button>
`
})
export class JazzDialog {
private _positionToggle = false;

jazzMessage = 'Jazzy jazz jazz';

constructor(public dialogRef: MdDialogRef<JazzDialog>) { }

togglePosition(): void {
this._positionToggle = !this._positionToggle;

if (this._positionToggle) {
this.dialogRef.updateDimensions(null, null, {
top: '25px',
left: '25px'
});
} else {
this.dialogRef.updateDimensions();
}
}
}


Expand Down Expand Up @@ -104,7 +121,7 @@ export class JazzDialog {
color="primary"
href="https://en.wikipedia.org/wiki/Neptune"
target="_blank">Read more on Wikipedia</a>
<button
md-button
color="secondary"
Expand Down
1 change: 1 addition & 0 deletions src/lib/core/core.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ export {
OverlayOrigin,
OverlayModule,
} from './overlay/overlay-directives';
export * from './overlay/position/global-position-strategy';
export * from './overlay/position/connected-position-strategy';
export * from './overlay/position/connected-position';
export {ScrollDispatcher} from './overlay/scroll/scroll-dispatcher';
Expand Down
28 changes: 27 additions & 1 deletion src/lib/dialog/dialog-ref.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {OverlayRef} from '../core';
import {OverlayRef, GlobalPositionStrategy} from '../core';
import {DialogPosition} from './dialog-config';
import {Observable} from 'rxjs/Observable';
import {Subject} from 'rxjs/Subject';

Expand Down Expand Up @@ -35,4 +36,29 @@ export class MdDialogRef<T> {
afterClosed(): Observable<any> {
return this._afterClosed.asObservable();
}

/**
* Updates the dialog's dimensions.
* @param width New width of the dialog.
* @param height New height of the dialog.
* @param position New position of the dialog.
*/
updateDimensions(width?: string, height?: string, position?: DialogPosition): void {
let strategy = this._overlayRef.getState().positionStrategy as GlobalPositionStrategy;

if (position && (position.left || position.right)) {
position.left ? strategy.left(position.left) : strategy.right(position.right);
} else {
strategy.centerHorizontally();
}

if (position && (position.top || position.bottom)) {
position.top ? strategy.top(position.top) : strategy.bottom(position.bottom);
} else {
strategy.centerVertically();
}

strategy.width(width).height(height);
this._overlayRef.updatePosition();
}
}
20 changes: 20 additions & 0 deletions src/lib/dialog/dialog.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,26 @@ describe('MdDialog', () => {
expect(overlayPane.style.marginRight).toBe('125px');
});

it('should allow for the dimensions to be updated', () => {
let dialogRef = dialog.open(PizzaMsg, {
position: {
left: '250px'
}
});

viewContainerFixture.detectChanges();

let overlayPane = overlayContainerElement.querySelector('.cdk-overlay-pane') as HTMLElement;

expect(overlayPane.style.marginLeft).toBe('250px');

dialogRef.updateDimensions(null, null, {
left: '500px'
});

expect(overlayPane.style.marginLeft).toBe('500px');
});

it('should close all of the dialogs', () => {
dialog.open(PizzaMsg);
dialog.open(PizzaMsg);
Expand Down
57 changes: 16 additions & 41 deletions src/lib/dialog/dialog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,11 +88,16 @@ export class MdDialog {

/**
* Creates the overlay into which the dialog will be loaded.
* @param dialogConfig The dialog configuration.
* @param config The dialog configuration.
* @returns A promise resolving to the OverlayRef for the created overlay.
*/
private _createOverlay(dialogConfig: MdDialogConfig): OverlayRef {
let overlayState = this._getOverlayState(dialogConfig);
private _createOverlay(config: MdDialogConfig): OverlayRef {
let overlayState = new OverlayState();
let strategy = this._overlay.position().global();

overlayState.hasBackdrop = true;
overlayState.positionStrategy = strategy;

return this._overlay.create(overlayState);
}

Expand Down Expand Up @@ -124,10 +129,10 @@ export class MdDialog {
component: ComponentType<T>,
dialogContainer: MdDialogContainer,
overlayRef: OverlayRef,
config?: MdDialogConfig): MdDialogRef<T> {
config: MdDialogConfig): MdDialogRef<T> {
// Create a reference to the dialog we're creating in order to give the user a handle
// to modify and close it.
let dialogRef = <MdDialogRef<T>> new MdDialogRef(overlayRef);
let dialogRef = new MdDialogRef<T>(overlayRef);

if (!dialogContainer.dialogConfig.disableClose) {
// When the dialog backdrop is clicked, we want to close it.
Expand All @@ -140,47 +145,17 @@ export class MdDialog {
// We create an injector specifically for the component we're instantiating so that it can
// inject the MdDialogRef. This allows a component loaded inside of a dialog to close itself
// and, optionally, to return a value.
let userInjector = config && config.viewContainerRef && config.viewContainerRef.injector;
let userInjector = config.viewContainerRef && config.viewContainerRef.injector;
let dialogInjector = new DialogInjector(dialogRef, userInjector || this._injector);

let contentPortal = new ComponentPortal(component, null, dialogInjector);

let contentRef = dialogContainer.attachComponentPortal(contentPortal);

dialogRef.componentInstance = contentRef.instance;
dialogRef.updateDimensions(config.width, config.height, config.position);

return dialogRef;
}

/**
* Creates an overlay state from a dialog config.
* @param dialogConfig The dialog configuration.
* @returns The overlay configuration.
*/
private _getOverlayState(dialogConfig: MdDialogConfig): OverlayState {
let state = new OverlayState();
let strategy = this._overlay.position().global();
let position = dialogConfig.position;

state.hasBackdrop = true;
state.positionStrategy = strategy;

if (position && (position.left || position.right)) {
position.left ? strategy.left(position.left) : strategy.right(position.right);
} else {
strategy.centerHorizontally();
}

if (position && (position.top || position.bottom)) {
position.top ? strategy.top(position.top) : strategy.bottom(position.bottom);
} else {
strategy.centerVertically();
}

strategy.width(dialogConfig.width).height(dialogConfig.height);

return state;
}

/**
* Removes a dialog from the array of open dialogs.
* @param dialogRef Dialog to be removed.
Expand All @@ -201,10 +176,10 @@ export class MdDialog {

/**
* Applies default options to the dialog config.
* @param dialogConfig Config to be modified.
* @param config Config to be modified.
* @returns The new configuration object.
*/
function _applyConfigDefaults(dialogConfig: MdDialogConfig): MdDialogConfig {
return extendObject(new MdDialogConfig(), dialogConfig);
function _applyConfigDefaults(config: MdDialogConfig): MdDialogConfig {
return extendObject(new MdDialogConfig(), config);
}

0 comments on commit 0c174d2

Please sign in to comment.