mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(dialog): add events (observables) for open & closeAll (#2522)
* added afterOpen & afterAllClosed observables to NgDialog + tests + demo * typo * fixed demo for aot * removed unused src argument in dialog demo * added viewContainerRef to dialog open tests * reworked dialog closeAll & open events based on feedback * added comment to change commit to the right username * added types for afterOpen & afterAllClosed * _afterAllClosed and _afterOpen subjects now delegate to state of parentDialog & removed spaces from inside import braces * fixed tslint error in dialog.ts
This commit is contained in:
committed by
Andrew Seguin
parent
6d0c40c806
commit
23ab15256f
@@ -8,7 +8,7 @@ import {MaterialModule, OverlayContainer,
|
||||
FullscreenOverlayContainer} from '@angular/material';
|
||||
import {DEMO_APP_ROUTES} from './demo-app/routes';
|
||||
import {ProgressBarDemo} from './progress-bar/progress-bar-demo';
|
||||
import {JazzDialog, ContentElementDialog, DialogDemo} from './dialog/dialog-demo';
|
||||
import {JazzDialog, ContentElementDialog, DialogDemo, IFrameDialog} from './dialog/dialog-demo';
|
||||
import {RippleDemo} from './ripple/ripple-demo';
|
||||
import {IconDemo} from './icon/icon-demo';
|
||||
import {GesturesDemo} from './gestures/gestures-demo';
|
||||
@@ -65,6 +65,7 @@ import {InputContainerDemo} from './input/input-container-demo';
|
||||
InputContainerDemo,
|
||||
JazzDialog,
|
||||
ContentElementDialog,
|
||||
IFrameDialog,
|
||||
ListDemo,
|
||||
LiveAnnouncerDemo,
|
||||
MdCheckboxDemoNestedChecklist,
|
||||
@@ -100,6 +101,7 @@ import {InputContainerDemo} from './input/input-container-demo';
|
||||
DemoApp,
|
||||
JazzDialog,
|
||||
ContentElementDialog,
|
||||
IFrameDialog,
|
||||
RotiniPanel,
|
||||
ScienceJoke,
|
||||
SpagettiPanel,
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import {Component} from '@angular/core';
|
||||
import {Component, Inject} from '@angular/core';
|
||||
import {DOCUMENT} from '@angular/platform-browser';
|
||||
import {MdDialog, MdDialogRef, MdDialogConfig} from '@angular/material';
|
||||
|
||||
@Component({
|
||||
@@ -23,7 +24,19 @@ export class DialogDemo {
|
||||
}
|
||||
};
|
||||
|
||||
constructor(public dialog: MdDialog) { }
|
||||
constructor(public dialog: MdDialog, @Inject(DOCUMENT) doc: any) {
|
||||
// Possible useful example for the open and closeAll events.
|
||||
// Adding a class to the body if a dialog opens and
|
||||
// removing it after all open dialogs are closed
|
||||
dialog.afterOpen.subscribe((ref: MdDialogRef<any>) => {
|
||||
if (!doc.body.classList.contains('no-scroll')) {
|
||||
doc.body.classList.add('no-scroll');
|
||||
}
|
||||
});
|
||||
dialog.afterAllClosed.subscribe(() => {
|
||||
doc.body.classList.remove('no-scroll');
|
||||
});
|
||||
}
|
||||
|
||||
openJazz() {
|
||||
this.dialogRef = this.dialog.open(JazzDialog, this.config);
|
||||
@@ -91,9 +104,46 @@ export class JazzDialog {
|
||||
color="primary"
|
||||
href="https://en.wikipedia.org/wiki/Neptune"
|
||||
target="_blank">Read more on Wikipedia</a>
|
||||
|
||||
<button
|
||||
md-button
|
||||
color="secondary"
|
||||
(click)="showInStackedDialog()">
|
||||
Show in Dialog</button>
|
||||
</md-dialog-actions>
|
||||
`
|
||||
})
|
||||
export class ContentElementDialog {
|
||||
actionsAlignment: string;
|
||||
|
||||
constructor(public dialog: MdDialog) { }
|
||||
|
||||
showInStackedDialog() {
|
||||
this.dialog.open(IFrameDialog);
|
||||
}
|
||||
}
|
||||
|
||||
@Component({
|
||||
selector: 'demo-iframe-dialog',
|
||||
styles: [
|
||||
`iframe {
|
||||
width: 800px;
|
||||
}`
|
||||
],
|
||||
template: `
|
||||
<h2 md-dialog-title>Neptune</h2>
|
||||
|
||||
<md-dialog-content>
|
||||
<iframe frameborder="0" src="https://en.wikipedia.org/wiki/Neptune"></iframe>
|
||||
</md-dialog-content>
|
||||
|
||||
<md-dialog-actions>
|
||||
<button
|
||||
md-raised-button
|
||||
color="primary"
|
||||
md-dialog-close>Close</button>
|
||||
</md-dialog-actions>
|
||||
`
|
||||
})
|
||||
export class IFrameDialog {
|
||||
}
|
||||
|
||||
@@ -150,6 +150,35 @@ describe('MdDialog', () => {
|
||||
expect(overlayContainerElement.querySelector('md-dialog-container')).toBeFalsy();
|
||||
});
|
||||
|
||||
it('should notify the observers if a dialog has been opened', () => {
|
||||
let ref: MdDialogRef<PizzaMsg>;
|
||||
dialog.afterOpen.subscribe(r => {
|
||||
ref = r;
|
||||
});
|
||||
expect(dialog.open(PizzaMsg, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
})).toBe(ref);
|
||||
});
|
||||
|
||||
it('should notify the observers if all open dialogs have finished closing', () => {
|
||||
const ref1 = dialog.open(PizzaMsg, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
});
|
||||
const ref2 = dialog.open(ContentElementDialog, {
|
||||
viewContainerRef: testViewContainerRef
|
||||
});
|
||||
let allClosed = false;
|
||||
|
||||
dialog.afterAllClosed.subscribe(() => {
|
||||
allClosed = true;
|
||||
});
|
||||
|
||||
ref1.close();
|
||||
expect(allClosed).toBeFalsy();
|
||||
ref2.close();
|
||||
expect(allClosed).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should should override the width of the overlay pane', () => {
|
||||
dialog.open(PizzaMsg, {
|
||||
width: '500px'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import {Injector, ComponentRef, Injectable, Optional, SkipSelf} from '@angular/core';
|
||||
import {Observable} from 'rxjs/Observable';
|
||||
import {Subject} from 'rxjs/Subject';
|
||||
|
||||
import {Overlay, OverlayRef, ComponentType, OverlayState, ComponentPortal} from '../core';
|
||||
import {extendObject} from '../core/util/object-extend';
|
||||
@@ -20,12 +22,30 @@ import {MdDialogContainer} from './dialog-container';
|
||||
@Injectable()
|
||||
export class MdDialog {
|
||||
private _openDialogsAtThisLevel: MdDialogRef<any>[] = [];
|
||||
private _afterAllClosedAtThisLevel = new Subject<void>();
|
||||
private _afterOpenAtThisLevel = new Subject<MdDialogRef<any>>();
|
||||
|
||||
/** Keeps track of the currently-open dialogs. */
|
||||
get _openDialogs(): MdDialogRef<any>[] {
|
||||
return this._parentDialog ? this._parentDialog._openDialogs : this._openDialogsAtThisLevel;
|
||||
}
|
||||
|
||||
/** Subject for notifying the user that all open dialogs have finished closing. */
|
||||
get _afterOpen(): Subject<MdDialogRef<any>> {
|
||||
return this._parentDialog ? this._parentDialog._afterOpen : this._afterOpenAtThisLevel;
|
||||
}
|
||||
/** Subject for notifying the user that a dialog has opened. */
|
||||
get _afterAllClosed(): Subject<void> {
|
||||
return this._parentDialog ?
|
||||
this._parentDialog._afterAllClosed : this._afterAllClosedAtThisLevel;
|
||||
}
|
||||
|
||||
/** Gets an observable that is notified when a dialog has been opened. */
|
||||
afterOpen: Observable<MdDialogRef<any>> = this._afterOpen.asObservable();
|
||||
|
||||
/** Gets an observable that is notified when all open dialog have finished closing. */
|
||||
afterAllClosed: Observable<void> = this._afterAllClosed.asObservable();
|
||||
|
||||
constructor(
|
||||
private _overlay: Overlay,
|
||||
private _injector: Injector,
|
||||
@@ -46,6 +66,7 @@ export class MdDialog {
|
||||
|
||||
this._openDialogs.push(dialogRef);
|
||||
dialogRef.afterClosed().subscribe(() => this._removeOpenDialog(dialogRef));
|
||||
this._afterOpen.next(dialogRef);
|
||||
|
||||
return dialogRef;
|
||||
}
|
||||
@@ -169,6 +190,11 @@ export class MdDialog {
|
||||
|
||||
if (index > -1) {
|
||||
this._openDialogs.splice(index, 1);
|
||||
|
||||
// no open dialogs are left, call next on afterAllClosed Subject
|
||||
if (!this._openDialogs.length) {
|
||||
this._afterAllClosed.next();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user