From 758b85186c8c12ba6a1b17f6e37c82f70bd706e2 Mon Sep 17 00:00:00 2001 From: Jeremy Elbourn Date: Fri, 15 Jul 2016 11:24:15 -0700 Subject: [PATCH] feat(dialog): add styles and ability to close. (#862) --- src/components/dialog/dialog-container.scss | 12 ++++++--- src/components/dialog/dialog-ref.ts | 29 ++++++++++++++++++++- src/components/dialog/dialog.spec.ts | 23 ++++++++++++++++ src/components/dialog/dialog.ts | 19 +++++++++----- src/demo-app/demo-app/demo-app.scss | 2 +- src/demo-app/demo-app/demo-app.ts | 5 ++-- src/demo-app/dialog/dialog-demo.html | 4 +++ src/demo-app/dialog/dialog-demo.ts | 15 +++++++++-- 8 files changed, 93 insertions(+), 16 deletions(-) diff --git a/src/components/dialog/dialog-container.scss b/src/components/dialog/dialog-container.scss index 7a91944e7e41..16d44466db02 100644 --- a/src/components/dialog/dialog-container.scss +++ b/src/components/dialog/dialog-container.scss @@ -1,8 +1,14 @@ @import 'elevation'; +@import 'default-theme'; + +$md-dialog-padding: 24px !default; :host { - // TODO(jelbourn): add real Material Design dialog styles. display: block; - background: deeppink; - @include md-elevation(2); + overflow: hidden; + + padding: $md-dialog-padding; + + background: md-color($md-background, dialog); + @include md-elevation(24); } diff --git a/src/components/dialog/dialog-ref.ts b/src/components/dialog/dialog-ref.ts index 141745dd4787..4be15c812788 100644 --- a/src/components/dialog/dialog-ref.ts +++ b/src/components/dialog/dialog-ref.ts @@ -1,3 +1,12 @@ +import {OverlayRef} from '@angular2-material/core/overlay/overlay-ref'; +import {Observable} from 'rxjs/Observable'; +import {Subject} from 'rxjs/Subject'; + + +// TODO(jelbourn): resizing +// TODO(jelbourn): afterOpen and beforeClose + + /** * Reference to a dialog opened via the MdDialog service. */ @@ -5,5 +14,23 @@ export class MdDialogRef { /** The instance of component opened into the dialog. */ componentInstance: T; - // TODO(jelbourn): Add methods to resize, close, and get results from the dialog. + /** Subject for notifying the user that the dialog has finished closing. */ + private _afterClosed: Subject = new Subject(); + + constructor(private _overlayRef: OverlayRef) { } + + /** + * Close the dialog. + * @param dialogResult Optional result to return to the dialog opener. + */ + close(dialogResult?: any): void { + this._overlayRef.dispose(); + this._afterClosed.next(dialogResult); + this._afterClosed.complete(); + } + + /** Gets an observable that is notified when the dialog is finished closing. */ + afterClosed(): Observable { + return this._afterClosed.asObservable(); + } } diff --git a/src/components/dialog/dialog.spec.ts b/src/components/dialog/dialog.spec.ts index c70636049e45..56723c2b15ce 100644 --- a/src/components/dialog/dialog.spec.ts +++ b/src/components/dialog/dialog.spec.ts @@ -84,6 +84,29 @@ describe('MdDialog', () => { detectChangesForDialogOpen(viewContainerFixture); })); + + it('should close a dialog and get back a result', async(() => { + let config = new MdDialogConfig(); + config.viewContainerRef = testViewContainerRef; + + dialog.open(PizzaMsg, config).then(dialogRef => { + viewContainerFixture.detectChanges(); + + let afterCloseResult: string; + dialogRef.afterClosed().subscribe(result => { + afterCloseResult = result; + }); + + dialogRef.close('Charmander'); + + viewContainerFixture.whenStable().then(() => { + expect(afterCloseResult).toBe('Charmander'); + expect(overlayContainerElement.childNodes.length).toBe(0); + }); + }); + + detectChangesForDialogOpen(viewContainerFixture); + })); }); diff --git a/src/components/dialog/dialog.ts b/src/components/dialog/dialog.ts index 73e700496669..53b462c66ef4 100644 --- a/src/components/dialog/dialog.ts +++ b/src/components/dialog/dialog.ts @@ -37,9 +37,12 @@ export class MdDialog { * @param config */ open(component: ComponentType, config: MdDialogConfig): Promise> { + let overlayRef: OverlayRef; + return this._createOverlay(config) - .then(overlayRef => this._attachDialogContainer(overlayRef, config)) - .then(containerRef => this._attachDialogContent(component, containerRef)); + .then(overlay => overlayRef = overlay) + .then(overlay => this._attachDialogContainer(overlay, config)) + .then(containerRef => this._attachDialogContent(component, containerRef, overlayRef)); } /** @@ -54,14 +57,14 @@ export class MdDialog { /** * Attaches an MdDialogContainer to a dialog's already-created overlay. - * @param overlayRef Reference to the dialog's underlying overlay. + * @param overlay Reference to the dialog's underlying overlay. * @param config The dialog configuration. * @returns A promise resolving to a ComponentRef for the attached container. */ - private _attachDialogContainer(overlayRef: OverlayRef, config: MdDialogConfig): + private _attachDialogContainer(overlay: OverlayRef, config: MdDialogConfig): Promise> { let containerPortal = new ComponentPortal(MdDialogContainer, config.viewContainerRef); - return overlayRef.attach(containerPortal).then(containerRef => { + return overlay.attach(containerPortal).then((containerRef: ComponentRef) => { // Pass the config directly to the container so that it can consume any relevant settings. containerRef.instance.dialogConfig = config; return containerRef; @@ -72,16 +75,18 @@ export class MdDialog { * Attaches the user-provided component to the already-created MdDialogContainer. * @param component The type of component being loaded into the dialog. * @param containerRef Reference to the wrapping MdDialogContainer. + * @param overlayRef Reference to the overlay in which the dialog resides. * @returns A promise resolving to the MdDialogRef that should be returned to the user. */ private _attachDialogContent( component: ComponentType, - containerRef: ComponentRef): Promise> { + containerRef: ComponentRef, + overlayRef: OverlayRef): Promise> { let dialogContainer = containerRef.instance; // Create a reference to the dialog we're creating in order to give the user a handle // to modify and close it. - let dialogRef = new MdDialogRef(); + let dialogRef = new MdDialogRef(overlayRef); // 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 diff --git a/src/demo-app/demo-app/demo-app.scss b/src/demo-app/demo-app/demo-app.scss index 9a85b466a86f..17338c88abf2 100644 --- a/src/demo-app/demo-app/demo-app.scss +++ b/src/demo-app/demo-app/demo-app.scss @@ -1,4 +1,4 @@ -.demo-root { +body { font-family: Roboto, 'Helvetica Neue', sans-serif; // Helps fonts on OSX looks more consistent with other systems diff --git a/src/demo-app/demo-app/demo-app.ts b/src/demo-app/demo-app/demo-app.ts index a864e7b960d4..28af2df7bf4b 100644 --- a/src/demo-app/demo-app/demo-app.ts +++ b/src/demo-app/demo-app/demo-app.ts @@ -1,4 +1,4 @@ -import {Component} from '@angular/core'; +import {Component, ViewEncapsulation} from '@angular/core'; import {ROUTER_DIRECTIVES} from '@angular/router'; import {Dir} from '@angular2-material/core/rtl/dir'; @@ -32,6 +32,7 @@ export class Home {} MD_LIST_DIRECTIVES, MdToolbar, ], - pipes: [] + pipes: [], + encapsulation: ViewEncapsulation.None, }) export class DemoApp { } diff --git a/src/demo-app/dialog/dialog-demo.html b/src/demo-app/dialog/dialog-demo.html index 3cc089d0c8ab..c87a0c9956a8 100644 --- a/src/demo-app/dialog/dialog-demo.html +++ b/src/demo-app/dialog/dialog-demo.html @@ -1,3 +1,7 @@

Dialog demo

+ +

+ Last close result: {{lastCloseResult}} +

diff --git a/src/demo-app/dialog/dialog-demo.ts b/src/demo-app/dialog/dialog-demo.ts index 07170611a7a0..a52b699cfde4 100644 --- a/src/demo-app/dialog/dialog-demo.ts +++ b/src/demo-app/dialog/dialog-demo.ts @@ -11,6 +11,7 @@ import {OVERLAY_PROVIDERS} from '@angular2-material/core/overlay/overlay'; }) export class DialogDemo { dialogRef: MdDialogRef; + lastCloseResult: string; constructor( public dialog: MdDialog, @@ -22,6 +23,11 @@ export class DialogDemo { this.dialog.open(JazzDialog, config).then(ref => { this.dialogRef = ref; + + this.dialogRef.afterClosed().subscribe(result => { + this.lastCloseResult = result; + this.dialogRef = null; + }); }); } } @@ -29,6 +35,11 @@ export class DialogDemo { @Component({ selector: 'demo-jazz-dialog', - template: `

It's Jazz!

` + template: ` +

It's Jazz!

+

+ ` }) -export class JazzDialog { } +export class JazzDialog { + constructor(public dialogRef: MdDialogRef) { } +}