Skip to content

Commit 569d482

Browse files
committed
feat(material-experimental): MDC-based version of dialog
1 parent 7e413c8 commit 569d482

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

48 files changed

+3234
-160
lines changed

.github/CODEOWNERS

+2
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,7 @@
164164
/src/dev-app/mdc-card/** @mmalerba
165165
/src/dev-app/mdc-checkbox/** @mmalerba
166166
/src/dev-app/mdc-chips/** @mmalerba
167+
/src/dev-app/mdc-dialog/** @devversion
167168
/src/dev-app/mdc-input/** @devversion @mmalerba
168169
/src/dev-app/mdc-list/** @mmalerba
169170
/src/dev-app/mdc-menu/** @crisbeto
@@ -221,6 +222,7 @@
221222
/src/e2e-app/mdc-card/** @mmalerba
222223
/src/e2e-app/mdc-checkbox/** @mmalerba
223224
/src/e2e-app/mdc-chips/** @mmalerba
225+
/src/e2e-app/mdc-dialog/** @devversion
224226
/src/e2e-app/mdc-menu/** @crisbeto
225227
/src/e2e-app/mdc-progress-bar/** @crisbeto
226228
/src/e2e-app/mdc-radio/** @mmalerba

src/cdk-experimental/dialog/dialog-container.ts

+19-8
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import {
1717
} from '@angular/cdk/portal';
1818
import {DOCUMENT} from '@angular/common';
1919
import {
20+
AfterViewInit,
2021
ChangeDetectionStrategy,
2122
ChangeDetectorRef,
2223
Component,
@@ -72,7 +73,7 @@ export function throwDialogContentAlreadyAttachedError() {
7273
'(@dialog.done)': '_animationDone.next($event)',
7374
},
7475
})
75-
export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
76+
export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy, AfterViewInit {
7677
private readonly _document: Document;
7778

7879
/** State of the dialog animation. */
@@ -150,6 +151,16 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
150151
});
151152
}
152153

154+
/** If the dialog view completes initialization, the open animation starts. */
155+
ngAfterViewInit() {
156+
// Save the previously focused element. This element will be re-focused
157+
// when the dialog closes.
158+
this._savePreviouslyFocusedElement();
159+
// Move focus onto the dialog immediately in order to prevent the user
160+
// from accidentally opening multiple dialogs at the same time.
161+
this._focusDialogContainer();
162+
}
163+
153164
/** Destroy focus trap to place focus back to the element focused before the dialog opened. */
154165
ngOnDestroy() {
155166
this._focusTrap.destroy();
@@ -165,7 +176,6 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
165176
throwDialogContentAlreadyAttachedError();
166177
}
167178

168-
this._savePreviouslyFocusedElement();
169179
return this._portalHost.attachComponentPortal(portal);
170180
}
171181

@@ -178,7 +188,6 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
178188
throwDialogContentAlreadyAttachedError();
179189
}
180190

181-
this._savePreviouslyFocusedElement();
182191
return this._portalHost.attachTemplatePortal(portal);
183192
}
184193

@@ -193,7 +202,6 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
193202
throwDialogContentAlreadyAttachedError();
194203
}
195204

196-
this._savePreviouslyFocusedElement();
197205
return this._portalHost.attachDomPortal(portal);
198206
}
199207

@@ -222,11 +230,14 @@ export class CdkDialogContainer extends BasePortalOutlet implements OnDestroy {
222230
private _savePreviouslyFocusedElement() {
223231
if (this._document) {
224232
this._elementFocusedBeforeDialogWasOpened = this._document.activeElement as HTMLElement;
233+
}
234+
}
225235

226-
// Move focus onto the dialog immediately in order to prevent the user from accidentally
227-
// opening multiple dialogs at the same time. Needs to be async, because the element
228-
// may not be focusable immediately.
229-
Promise.resolve().then(() => this._elementRef.nativeElement.focus());
236+
/** Focuses the dialog container. */
237+
private _focusDialogContainer() {
238+
// Note that there is no focus method when rendering on the server.
239+
if (this._elementRef.nativeElement.focus) {
240+
this._elementRef.nativeElement.focus();
230241
}
231242
}
232243

src/dev-app/BUILD.bazel

+2
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ ng_module(
4848
"//src/dev-app/mdc-card",
4949
"//src/dev-app/mdc-checkbox",
5050
"//src/dev-app/mdc-chips",
51+
"//src/dev-app/mdc-dialog",
5152
"//src/dev-app/mdc-input",
5253
"//src/dev-app/mdc-list",
5354
"//src/dev-app/mdc-menu",
@@ -95,6 +96,7 @@ sass_binary(
9596
],
9697
deps = [
9798
"//src/material-experimental/column-resize:column_resize_scss_lib",
99+
"//src/material-experimental/mdc-dialog:mdc_dialog_scss_lib",
98100
"//src/material-experimental/mdc-theming:all_themes",
99101
"//src/material-experimental/mdc-typography:all_typography",
100102
"//src/material-experimental/popover-edit:popover_edit_scss_lib",

src/dev-app/dev-app/dev-app-layout.ts

+1
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ export class DevAppLayout {
7575
{name: 'MDC Card', route: '/mdc-card'},
7676
{name: 'MDC Checkbox', route: '/mdc-checkbox'},
7777
{name: 'MDC Chips', route: '/mdc-chips'},
78+
{name: 'MDC Dialog', route: '/mdc-dialog'},
7879
{name: 'MDC Input', route: '/mdc-input'},
7980
{name: 'MDC List', route: '/mdc-list'},
8081
{name: 'MDC Menu', route: '/mdc-menu'},

src/dev-app/dev-app/routes.ts

+1
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ export const DEV_APP_ROUTES: Routes = [
6868
loadChildren: 'mdc-progress-bar/mdc-progress-bar-demo-module#MdcProgressBarDemoModule'
6969
},
7070
{path: 'mdc-chips', loadChildren: 'mdc-chips/mdc-chips-demo-module#MdcChipsDemoModule'},
71+
{path: 'mdc-dialog', loadChildren: 'mdc-dialog/mdc-dialog-demo-module#MdcDialogDemoModule'},
7172
{path: 'mdc-input', loadChildren: 'mdc-input/mdc-input-demo-module#MdcInputDemoModule'},
7273
{path: 'mdc-list', loadChildren: 'mdc-list/mdc-list-demo-module#MdcListDemoModule'},
7374
{path: 'mdc-menu', loadChildren: 'mdc-menu/mdc-menu-demo-module#MdcMenuDemoModule'},

src/dev-app/mdc-dialog/BUILD.bazel

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
load("//tools:defaults.bzl", "ng_module", "sass_binary")
2+
3+
package(default_visibility = ["//visibility:public"])
4+
5+
ng_module(
6+
name = "mdc-dialog",
7+
srcs = glob(["**/*.ts"]),
8+
assets = [
9+
"mdc-dialog-demo.html",
10+
":mdc_dialog_demo_scss",
11+
],
12+
deps = [
13+
"//src/material-experimental/mdc-dialog",
14+
"//src/material/button",
15+
"//src/material/card",
16+
"//src/material/checkbox",
17+
"//src/material/form-field",
18+
"//src/material/input",
19+
"//src/material/select",
20+
"@npm//@angular/router",
21+
],
22+
)
23+
24+
sass_binary(
25+
name = "mdc_dialog_demo_scss",
26+
src = "mdc-dialog-demo.scss",
27+
)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.io/license
7+
*/
8+
9+
import {NgModule} from '@angular/core';
10+
import {FormsModule} from '@angular/forms';
11+
import {MatDialogModule} from '@angular/material-experimental/mdc-dialog';
12+
import {MatButtonModule} from '@angular/material/button';
13+
import {MatCardModule} from '@angular/material/card';
14+
import {MatCheckboxModule} from '@angular/material/checkbox';
15+
import {MatFormFieldModule} from '@angular/material/form-field';
16+
import {MatInputModule} from '@angular/material/input';
17+
import {MatSelectModule} from '@angular/material/select';
18+
import {RouterModule} from '@angular/router';
19+
import {ContentElementDialog, DialogDemo, IFrameDialog, JazzDialog} from './mdc-dialog-demo';
20+
21+
@NgModule({
22+
imports: [
23+
FormsModule,
24+
MatButtonModule,
25+
MatCardModule,
26+
MatCheckboxModule,
27+
MatDialogModule,
28+
MatFormFieldModule,
29+
MatInputModule,
30+
MatSelectModule,
31+
RouterModule.forChild([{path: '', component: DialogDemo}]),
32+
],
33+
declarations: [ContentElementDialog, DialogDemo, IFrameDialog, JazzDialog],
34+
})
35+
export class MdcDialogDemoModule {
36+
}
+131
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,131 @@
1+
<h1>Dialog demo</h1>
2+
3+
<button mat-raised-button color="primary" (click)="openJazz()">
4+
Open dialog
5+
</button>
6+
<button mat-raised-button color="accent" (click)="openContentElement()">
7+
Open dialog with content elements
8+
</button>
9+
<button mat-raised-button color="accent" (click)="openTemplate()">
10+
Open dialog with template content
11+
</button>
12+
13+
<p>
14+
<mat-checkbox [(ngModel)]="enableLegacyPadding">Enable legacy padding</mat-checkbox>
15+
</p>
16+
17+
<mat-card class="demo-dialog-card">
18+
<mat-card-content>
19+
<h2>Dialog dimensions</h2>
20+
21+
<p>
22+
<mat-form-field>
23+
<mat-label>Width</mat-label>
24+
<input matInput [(ngModel)]="config.width">
25+
</mat-form-field>
26+
<mat-form-field>
27+
<mat-label>Height</mat-label>
28+
<input matInput [(ngModel)]="config.height">
29+
</mat-form-field>
30+
</p>
31+
32+
<p>
33+
<mat-form-field>
34+
<mat-label>Min width</mat-label>
35+
<input matInput [(ngModel)]="config.minWidth">
36+
</mat-form-field>
37+
<mat-form-field>
38+
<mat-label>Min height</mat-label>
39+
<input matInput [(ngModel)]="config.minHeight">
40+
</mat-form-field>
41+
</p>
42+
43+
<p>
44+
<mat-form-field>
45+
<mat-label>Max width</mat-label>
46+
<input matInput [(ngModel)]="config.maxWidth">
47+
</mat-form-field>
48+
<mat-form-field>
49+
<mat-label>Max height</mat-label>
50+
<input matInput [(ngModel)]="config.maxHeight">
51+
</mat-form-field>
52+
</p>
53+
54+
<h2>Dialog position</h2>
55+
56+
<p>
57+
<mat-form-field>
58+
<mat-label>Top</mat-label>
59+
<input matInput [(ngModel)]="config.position.top" (change)="config.position.bottom = ''">
60+
</mat-form-field>
61+
<mat-form-field>
62+
<mat-label>Bottom</mat-label>
63+
<input matInput [(ngModel)]="config.position.bottom" (change)="config.position.top = ''">
64+
</mat-form-field>
65+
</p>
66+
67+
<p>
68+
<mat-form-field>
69+
<mat-label>Left</mat-label>
70+
<input matInput [(ngModel)]="config.position.left" (change)="config.position.right = ''">
71+
</mat-form-field>
72+
<mat-form-field>
73+
<mat-label>Right</mat-label>
74+
<input matInput [(ngModel)]="config.position.right" (change)="config.position.left = ''">
75+
</mat-form-field>
76+
</p>
77+
78+
<h2>Dialog backdrop</h2>
79+
80+
<p>
81+
<mat-form-field>
82+
<mat-label>Backdrop class</mat-label>
83+
<input matInput [(ngModel)]="config.backdropClass">
84+
</mat-form-field>
85+
</p>
86+
87+
<mat-checkbox [(ngModel)]="config.hasBackdrop">Has backdrop</mat-checkbox>
88+
89+
<h2>Other options</h2>
90+
91+
<p>
92+
<mat-form-field>
93+
<mat-label>Button alignment</mat-label>
94+
<mat-select [(ngModel)]="actionsAlignment">
95+
<mat-option>Start</mat-option>
96+
<mat-option value="end">End</mat-option>
97+
<mat-option value="center">Center</mat-option>
98+
</mat-select>
99+
</mat-form-field>
100+
</p>
101+
102+
<p>
103+
<mat-form-field>
104+
<mat-label>Dialog message</mat-label>
105+
<input matInput [(ngModel)]="config.data.message">
106+
</mat-form-field>
107+
</p>
108+
109+
<p>
110+
<mat-checkbox [(ngModel)]="config.disableClose">Disable close</mat-checkbox>
111+
</p>
112+
</mat-card-content>
113+
</mat-card>
114+
115+
<p>Last afterClosed result: {{lastAfterClosedResult}}</p>
116+
<p>Last beforeClose result: {{lastBeforeCloseResult}}</p>
117+
118+
<ng-template let-data let-dialogRef="dialogRef">
119+
I'm a template dialog. I've been opened {{numTemplateOpens}} times!
120+
121+
<p>It's Jazz!</p>
122+
123+
<mat-form-field>
124+
<mat-label>How much?</mat-label>
125+
<input matInput #howMuch>
126+
</mat-form-field>
127+
128+
<p> {{ data.message }} </p>
129+
<button type="button" (click)="dialogRef.close(howMuch.value)" cdkFocusInitial>Close dialog</button>
130+
<button (click)="dialogRef.updateSize('500px', '500px').updatePosition({top: '25px', left: '25px'});">Change dimensions</button>
131+
</ng-template>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
.demo-dialog-card {
2+
max-width: 405px;
3+
margin: 20px 0;
4+
}
5+
6+
button {
7+
margin-right: 8px;
8+
9+
[dir='rtl'] & {
10+
margin-left: 8px;
11+
margin-right: 0;
12+
}
13+
}

0 commit comments

Comments
 (0)