From 29cbe61296610648d5c44d705d3b00a2d4b2efde Mon Sep 17 00:00:00 2001
From: Kristiyan Kostadinov
Date: Mon, 6 Feb 2017 23:57:59 +0100
Subject: [PATCH] feat(dialog): add a config option for passing in data (#2266)
* feat(dialog): add a config option for passing in data
Adds the ability to pass in data to a dialog via the `data` property. While this was previously possible through the `dialogRef.componentInstance.someUserSuppliedProperty`, it wasn't the most intuitive. The new approach looks like this:
```
dialog.open(SomeDialog, {
data: {
hello: 'world'
}
});
class SometDialog {
constructor(data: MdDialogData) {
console.log(data['hello']);
}
}
```
Fixes #2181.
* Switch to using an OpaqueToken.
* chore: fix aot errors
---
src/demo-app/dialog/dialog-demo.html | 10 +++++-
src/demo-app/dialog/dialog-demo.ts | 18 +++++++----
src/lib/dialog/dialog-config.ts | 4 ++-
src/lib/dialog/dialog-injector.ts | 12 +++++--
src/lib/dialog/dialog.spec.ts | 48 ++++++++++++++++++++++++++--
src/lib/dialog/dialog.ts | 4 +--
src/lib/dialog/index.ts | 1 +
7 files changed, 81 insertions(+), 16 deletions(-)
diff --git a/src/demo-app/dialog/dialog-demo.html b/src/demo-app/dialog/dialog-demo.html
index 53734bbbfdff..0391728e7cca 100644
--- a/src/demo-app/dialog/dialog-demo.html
+++ b/src/demo-app/dialog/dialog-demo.html
@@ -46,7 +46,15 @@ Other options
- Disable close
+
+
+
+
+
+
+
+ Disable close
+
diff --git a/src/demo-app/dialog/dialog-demo.ts b/src/demo-app/dialog/dialog-demo.ts
index 5e91c097f9aa..3c4475487502 100644
--- a/src/demo-app/dialog/dialog-demo.ts
+++ b/src/demo-app/dialog/dialog-demo.ts
@@ -1,6 +1,7 @@
import {Component, Inject} from '@angular/core';
import {DOCUMENT} from '@angular/platform-browser';
-import {MdDialog, MdDialogRef, MdDialogConfig} from '@angular/material';
+import {MdDialog, MdDialogRef, MdDialogConfig, MD_DIALOG_DATA} from '@angular/material';
+
@Component({
moduleId: module.id,
@@ -21,6 +22,9 @@ export class DialogDemo {
bottom: '',
left: '',
right: ''
+ },
+ data: {
+ message: 'Jazzy jazz jazz'
}
};
@@ -41,7 +45,7 @@ export class DialogDemo {
openJazz() {
this.dialogRef = this.dialog.open(JazzDialog, this.config);
- this.dialogRef.afterClosed().subscribe(result => {
+ this.dialogRef.afterClosed().subscribe((result: string) => {
this.lastCloseResult = result;
this.dialogRef = null;
});
@@ -59,13 +63,13 @@ export class DialogDemo {
template: `
It's Jazz!
How much?
- {{ jazzMessage }}
+ {{ data.message }}
Close dialog `
})
export class JazzDialog {
- jazzMessage = 'Jazzy jazz jazz';
-
- constructor(public dialogRef: MdDialogRef) { }
+ constructor(
+ public dialogRef: MdDialogRef,
+ @Inject(MD_DIALOG_DATA) public data: any) { }
}
@@ -104,7 +108,7 @@ export class JazzDialog {
color="primary"
href="https://en.wikipedia.org/wiki/Neptune"
target="_blank">Read more on Wikipedia
-
+
, private _parentInjector: Injector) { }
+ constructor(
+ private _parentInjector: Injector,
+ private _dialogRef: MdDialogRef,
+ private _data: any) { }
get(token: any, notFoundValue?: any): any {
if (token === MdDialogRef) {
return this._dialogRef;
}
+ if (token === MD_DIALOG_DATA && this._data) {
+ return this._data;
+ }
+
return this._parentInjector.get(token, notFoundValue);
}
}
diff --git a/src/lib/dialog/dialog.spec.ts b/src/lib/dialog/dialog.spec.ts
index e4196924deaa..7c48bf9a2871 100644
--- a/src/lib/dialog/dialog.spec.ts
+++ b/src/lib/dialog/dialog.spec.ts
@@ -7,13 +7,21 @@ import {
TestBed,
tick,
} from '@angular/core/testing';
+import {NgModule,
+ Component,
+ Directive,
+ ViewChild,
+ ViewContainerRef,
+ Injector,
+ Inject,
+} from '@angular/core';
import {By} from '@angular/platform-browser';
-import {NgModule, Component, Directive, ViewChild, ViewContainerRef, Injector} from '@angular/core';
import {MdDialogModule} from './index';
import {MdDialog} from './dialog';
import {OverlayContainer} from '../core';
import {MdDialogRef} from './dialog-ref';
import {MdDialogContainer} from './dialog-container';
+import {MD_DIALOG_DATA} from './dialog-injector';
describe('MdDialog', () => {
@@ -271,6 +279,28 @@ describe('MdDialog', () => {
expect(overlayContainerElement.querySelectorAll('md-dialog-container').length).toBe(0);
});
+ describe('passing in data', () => {
+ it('should be able to pass in data', () => {
+ let config = {
+ data: {
+ stringParam: 'hello',
+ dateParam: new Date()
+ }
+ };
+
+ let instance = dialog.open(DialogWithInjectedData, config).componentInstance;
+
+ expect(instance.data.stringParam).toBe(config.data.stringParam);
+ expect(instance.data.dateParam).toBe(config.data.dateParam);
+ });
+
+ it('should throw if injected data is expected but none is passed', () => {
+ expect(() => {
+ dialog.open(DialogWithInjectedData);
+ }).toThrow();
+ });
+ });
+
describe('disableClose option', () => {
it('should prevent closing via clicks on the backdrop', () => {
dialog.open(PizzaMsg, {
@@ -505,19 +535,31 @@ class ComponentThatProvidesMdDialog {
constructor(public dialog: MdDialog) {}
}
+/** Simple component for testing ComponentPortal. */
+@Component({template: ''})
+class DialogWithInjectedData {
+ constructor(@Inject(MD_DIALOG_DATA) public data: any) { }
+}
+
// Create a real (non-test) NgModule as a workaround for
// https://github.com/angular/angular/issues/10760
const TEST_DIRECTIVES = [
ComponentWithChildViewContainer,
PizzaMsg,
DirectiveWithViewContainer,
- ContentElementDialog
+ ContentElementDialog,
+ DialogWithInjectedData
];
@NgModule({
imports: [MdDialogModule],
exports: TEST_DIRECTIVES,
declarations: TEST_DIRECTIVES,
- entryComponents: [ComponentWithChildViewContainer, PizzaMsg, ContentElementDialog],
+ entryComponents: [
+ ComponentWithChildViewContainer,
+ PizzaMsg,
+ ContentElementDialog,
+ DialogWithInjectedData
+ ],
})
class DialogTestModule { }
diff --git a/src/lib/dialog/dialog.ts b/src/lib/dialog/dialog.ts
index 93e48cd6b2fc..4d4ed5c14b86 100644
--- a/src/lib/dialog/dialog.ts
+++ b/src/lib/dialog/dialog.ts
@@ -129,7 +129,7 @@ export class MdDialog {
// to modify and close it.
let dialogRef = > new MdDialogRef(overlayRef);
- if (!dialogContainer.dialogConfig.disableClose) {
+ if (!config.disableClose) {
// When the dialog backdrop is clicked, we want to close it.
overlayRef.backdropClick().first().subscribe(() => dialogRef.close());
}
@@ -141,7 +141,7 @@ export class MdDialog {
// 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 dialogInjector = new DialogInjector(dialogRef, userInjector || this._injector);
+ let dialogInjector = new DialogInjector(userInjector || this._injector, dialogRef, config.data);
let contentPortal = new ComponentPortal(component, null, dialogInjector);
diff --git a/src/lib/dialog/index.ts b/src/lib/dialog/index.ts
index e14bc904b78b..664f8e4b0ab5 100644
--- a/src/lib/dialog/index.ts
+++ b/src/lib/dialog/index.ts
@@ -57,3 +57,4 @@ export * from './dialog-container';
export * from './dialog-content-directives';
export * from './dialog-config';
export * from './dialog-ref';
+export {MD_DIALOG_DATA} from './dialog-injector';