diff --git a/src/components-examples/material/dialog/dialog-animations/dialog-animations-example-dialog.html b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example-dialog.html
new file mode 100644
index 000000000000..1fabf9a6d0c9
--- /dev/null
+++ b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example-dialog.html
@@ -0,0 +1,8 @@
+
Delete file
+
+ Would you like to delete cat.jpeg?
+
+
+
+
+
diff --git a/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.css b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.css
new file mode 100644
index 000000000000..83117bf83c68
--- /dev/null
+++ b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.css
@@ -0,0 +1,3 @@
+button {
+ margin-right: 8px;
+}
diff --git a/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.html b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.html
new file mode 100644
index 000000000000..e50b6eecdcdb
--- /dev/null
+++ b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.html
@@ -0,0 +1,2 @@
+
+
diff --git a/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.ts b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.ts
new file mode 100644
index 000000000000..81d23753fee9
--- /dev/null
+++ b/src/components-examples/material/dialog/dialog-animations/dialog-animations-example.ts
@@ -0,0 +1,30 @@
+import {Component} from '@angular/core';
+import {MatDialog, MatDialogRef} from '@angular/material/dialog';
+
+/**
+ * @title Dialog Animations
+ */
+@Component({
+ selector: 'dialog-animations-example',
+ styleUrls: ['dialog-animations-example.css'],
+ templateUrl: 'dialog-animations-example.html',
+})
+export class DialogAnimationsExample {
+ constructor(public dialog: MatDialog) {}
+
+ openDialog(enterAnimationDuration: string, exitAnimationDuration: string): void {
+ this.dialog.open(DialogAnimationsExampleDialog, {
+ width: '250px',
+ enterAnimationDuration,
+ exitAnimationDuration,
+ });
+ }
+}
+
+@Component({
+ selector: 'dialog-animations-example-dialog',
+ templateUrl: 'dialog-animations-example-dialog.html',
+})
+export class DialogAnimationsExampleDialog {
+ constructor(public dialogRef: MatDialogRef) {}
+}
diff --git a/src/components-examples/material/dialog/index.ts b/src/components-examples/material/dialog/index.ts
index 187a4df2419d..3230cdd52d10 100644
--- a/src/components-examples/material/dialog/index.ts
+++ b/src/components-examples/material/dialog/index.ts
@@ -23,6 +23,10 @@ import {
DialogFromMenuExampleDialog,
} from './dialog-from-menu/dialog-from-menu-example';
import {DialogHarnessExample} from './dialog-harness/dialog-harness-example';
+import {
+ DialogAnimationsExample,
+ DialogAnimationsExampleDialog,
+} from './dialog-animations/dialog-animations-example';
export {
DialogContentExample,
@@ -36,6 +40,8 @@ export {
DialogHarnessExample,
DialogOverviewExample,
DialogOverviewExampleDialog,
+ DialogAnimationsExample,
+ DialogAnimationsExampleDialog,
};
const EXAMPLES = [
@@ -50,6 +56,8 @@ const EXAMPLES = [
DialogHarnessExample,
DialogOverviewExample,
DialogOverviewExampleDialog,
+ DialogAnimationsExample,
+ DialogAnimationsExampleDialog,
];
@NgModule({
diff --git a/src/dev-app/dialog/dialog-demo.html b/src/dev-app/dialog/dialog-demo.html
index 7605af0d8911..49ad140ae1de 100644
--- a/src/dev-app/dialog/dialog-demo.html
+++ b/src/dev-app/dialog/dialog-demo.html
@@ -102,6 +102,17 @@ Other options
+
+
+ Enter duration
+
+
+
+ Exit duration
+
+
+
+
Disable close
diff --git a/src/dev-app/dialog/dialog-demo.ts b/src/dev-app/dialog/dialog-demo.ts
index cc2ce89bcabd..851f00ecd602 100644
--- a/src/dev-app/dialog/dialog-demo.ts
+++ b/src/dev-app/dialog/dialog-demo.ts
@@ -31,6 +31,8 @@ export class DialogDemo {
height: '',
minWidth: '',
minHeight: '',
+ enterAnimationDuration: defaultDialogConfig.enterAnimationDuration,
+ exitAnimationDuration: defaultDialogConfig.exitAnimationDuration,
maxWidth: defaultDialogConfig.maxWidth,
maxHeight: '',
position: {
diff --git a/src/material/dialog/dialog-animations.ts b/src/material/dialog/dialog-animations.ts
index 815c140ef9aa..960b4879fc96 100644
--- a/src/material/dialog/dialog-animations.ts
+++ b/src/material/dialog/dialog-animations.ts
@@ -34,14 +34,17 @@ export const matDialogAnimations: {
transition(
'* => enter',
group([
- animate('150ms cubic-bezier(0, 0, 0.2, 1)', style({transform: 'none', opacity: 1})),
+ animate(
+ '{{enterAnimationDuration}} cubic-bezier(0, 0, 0.2, 1)',
+ style({transform: 'none', opacity: 1}),
+ ),
query('@*', animateChild(), {optional: true}),
]),
),
transition(
'* => void, * => exit',
group([
- animate('75ms cubic-bezier(0.4, 0.0, 0.2, 1)', style({opacity: 0})),
+ animate('{{exitAnimationDuration}} cubic-bezier(0.4, 0.0, 0.2, 1)', style({opacity: 0})),
query('@*', animateChild(), {optional: true}),
]),
),
diff --git a/src/material/dialog/dialog-config.ts b/src/material/dialog/dialog-config.ts
index 9fa06481bf1f..79854fb8f8f6 100644
--- a/src/material/dialog/dialog-config.ts
+++ b/src/material/dialog/dialog-config.ts
@@ -126,5 +126,11 @@ export class MatDialogConfig {
/** Alternate `ComponentFactoryResolver` to use when resolving the associated component. */
componentFactoryResolver?: ComponentFactoryResolver;
+ /** Duration of the enter animation. Has to be a valid CSS value (e.g. 100ms). */
+ enterAnimationDuration?: string = '150ms';
+
+ /** Duration of the exit animation. Has to be a valid CSS value (e.g. 50ms). */
+ exitAnimationDuration?: string = '75ms';
+
// TODO(jelbourn): add configuration for lifecycle hooks, ARIA labelling.
}
diff --git a/src/material/dialog/dialog-container.ts b/src/material/dialog/dialog-container.ts
index 162b3e94d9c8..4e3300f42232 100644
--- a/src/material/dialog/dialog-container.ts
+++ b/src/material/dialog/dialog-container.ts
@@ -312,7 +312,7 @@ export abstract class _MatDialogContainerBase extends BasePortalOutlet {
'[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',
'[attr.aria-label]': '_config.ariaLabel',
'[attr.aria-describedby]': '_config.ariaDescribedBy || null',
- '[@dialogContainer]': '_state',
+ '[@dialogContainer]': `_getAnimationState()`,
'(@dialogContainer.start)': '_onAnimationStart($event)',
'(@dialogContainer.done)': '_onAnimationDone($event)',
},
@@ -360,4 +360,14 @@ export class MatDialogContainer extends _MatDialogContainerBase {
this._trapFocus();
}
}
+
+ _getAnimationState() {
+ return {
+ value: this._state,
+ params: {
+ enterAnimationDuration: this._config.enterAnimationDuration || '150ms',
+ exitAnimationDuration: this._config.exitAnimationDuration || '75ms',
+ },
+ };
+ }
}
diff --git a/src/material/dialog/dialog.md b/src/material/dialog/dialog.md
index 6aefedfce50b..49795fc4db2c 100644
--- a/src/material/dialog/dialog.md
+++ b/src/material/dialog/dialog.md
@@ -118,6 +118,44 @@ You can control which elements are tab stops with the `tabindex` attribute
+### Configuring dialog content via `entryComponents`
+
+Because `MatDialog` instantiates components at run-time, the Angular compiler needs extra
+information to create the necessary `ComponentFactory` for your dialog content component.
+
+For any component loaded into a dialog, you must include your component class in the list of
+`entryComponents` in your NgModule definition so that the Angular compiler knows to create
+the `ComponentFactory` for it.
+
+```ts
+@NgModule({
+ imports: [
+ // ...
+ MatDialogModule
+ ],
+
+ declarations: [
+ AppComponent,
+ ExampleDialogComponent
+ ],
+
+ entryComponents: [
+ ExampleDialogComponent
+ ],
+
+ providers: [],
+ bootstrap: [AppComponent]
+})
+export class AppModule {}
+```
+
+### Controlling the dialog animation
+You can control the duration of the dialog's enter and exit animations using the
+`enterAnimationDuration` and `exitAnimationDuration` options. If you want to disable the dialog's
+animation completely, you can do so by setting the properties to `0ms`.
+
+
+
### Accessibility
`MatDialog` creates modal dialogs that implements the ARIA `role="dialog"` pattern by default.
diff --git a/src/material/dialog/dialog.spec.ts b/src/material/dialog/dialog.spec.ts
index c874e01e4389..63221b92ea1e 100644
--- a/src/material/dialog/dialog.spec.ts
+++ b/src/material/dialog/dialog.spec.ts
@@ -1959,6 +1959,8 @@ describe('MatDialog with default options', () => {
minHeight: '50px',
maxWidth: '150px',
maxHeight: '150px',
+ enterAnimationDuration: '100ms',
+ exitAnimationDuration: '50ms',
autoFocus: false,
};
diff --git a/tools/public_api_guard/material/dialog.md b/tools/public_api_guard/material/dialog.md
index e8cbe9d65967..2a6049b393eb 100644
--- a/tools/public_api_guard/material/dialog.md
+++ b/tools/public_api_guard/material/dialog.md
@@ -168,6 +168,8 @@ export class MatDialogConfig {
delayFocusTrap?: boolean;
direction?: Direction;
disableClose?: boolean;
+ enterAnimationDuration?: string;
+ exitAnimationDuration?: string;
hasBackdrop?: boolean;
height?: string;
id?: string;
@@ -186,6 +188,14 @@ export class MatDialogConfig {
// @public
export class MatDialogContainer extends _MatDialogContainerBase {
+ // (undocumented)
+ _getAnimationState(): {
+ value: "enter" | "void" | "exit";
+ params: {
+ enterAnimationDuration: string;
+ exitAnimationDuration: string;
+ };
+ };
// (undocumented)
_initializeWithAttachedContent(): void;
_onAnimationDone({ toState, totalTime }: AnimationEvent_2): void;