Skip to content

Commit 578b977

Browse files
committed
refactor(material/dialog): switch to CDK dialog internally
Switches the Material dialog to be based on the CDK dialog.
1 parent fb4e395 commit 578b977

File tree

16 files changed

+252
-676
lines changed

16 files changed

+252
-676
lines changed

src/material-experimental/mdc-dialog/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ ng_test_library(
6464
":mdc-dialog",
6565
"//src/cdk/a11y",
6666
"//src/cdk/bidi",
67+
"//src/cdk/dialog",
6768
"//src/cdk/keycodes",
6869
"//src/cdk/overlay",
6970
"//src/cdk/platform",

src/material-experimental/mdc-dialog/dialog-container.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,18 @@
77
*/
88

99
import {FocusMonitor, FocusTrapFactory, InteractivityChecker} from '@angular/cdk/a11y';
10+
import {OverlayRef} from '@angular/cdk/overlay';
1011
import {DOCUMENT} from '@angular/common';
1112
import {
1213
ChangeDetectionStrategy,
13-
ChangeDetectorRef,
1414
Component,
1515
ElementRef,
1616
Inject,
1717
OnDestroy,
1818
Optional,
1919
ViewEncapsulation,
2020
NgZone,
21+
AfterViewInit,
2122
} from '@angular/core';
2223
import {MatDialogConfig, _MatDialogContainerBase} from '@angular/material/dialog';
2324
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
@@ -38,16 +39,19 @@ import {cssClasses, numbers} from '@material/dialog';
3839
host: {
3940
'class': 'mat-mdc-dialog-container mdc-dialog',
4041
'tabindex': '-1',
41-
'aria-modal': 'true',
42-
'[id]': '_id',
42+
'[attr.aria-modal]': '_config.ariaModal',
43+
'[id]': '_config.id',
4344
'[attr.role]': '_config.role',
4445
'[attr.aria-labelledby]': '_config.ariaLabel ? null : _ariaLabelledBy',
4546
'[attr.aria-label]': '_config.ariaLabel',
4647
'[attr.aria-describedby]': '_config.ariaDescribedBy || null',
4748
'[class._mat-animation-noopable]': '!_animationsEnabled',
4849
},
4950
})
50-
export class MatDialogContainer extends _MatDialogContainerBase implements OnDestroy {
51+
export class MatDialogContainer
52+
extends _MatDialogContainerBase
53+
implements OnDestroy, AfterViewInit
54+
{
5155
/** Whether animations are enabled. */
5256
_animationsEnabled: boolean = this._animationMode !== 'NoopAnimations';
5357

@@ -67,30 +71,31 @@ export class MatDialogContainer extends _MatDialogContainerBase implements OnDes
6771
constructor(
6872
elementRef: ElementRef,
6973
focusTrapFactory: FocusTrapFactory,
70-
changeDetectorRef: ChangeDetectorRef,
7174
@Optional() @Inject(DOCUMENT) document: any,
72-
config: MatDialogConfig,
75+
dialogConfig: MatDialogConfig,
7376
checker: InteractivityChecker,
7477
ngZone: NgZone,
78+
overlayRef: OverlayRef,
7579
@Optional() @Inject(ANIMATION_MODULE_TYPE) private _animationMode?: string,
7680
focusMonitor?: FocusMonitor,
7781
) {
7882
super(
7983
elementRef,
8084
focusTrapFactory,
81-
changeDetectorRef,
8285
document,
83-
config,
86+
dialogConfig,
8487
checker,
8588
ngZone,
89+
overlayRef,
8690
focusMonitor,
8791
);
8892
}
8993

90-
override _initializeWithAttachedContent() {
94+
override ngAfterViewInit(): void {
9195
// Delegate to the original dialog-container initialization (i.e. saving the
9296
// previous element, setting up the focus trap and moving focus to the container).
93-
super._initializeWithAttachedContent();
97+
super.ngAfterViewInit();
98+
9499
// Note: Usually we would be able to use the MDC dialog foundation here to handle
95100
// the dialog animation for us, but there are a few reasons why we just leverage
96101
// their styles and not use the runtime foundation code:
@@ -103,7 +108,9 @@ export class MatDialogContainer extends _MatDialogContainerBase implements OnDes
103108
this._startOpenAnimation();
104109
}
105110

106-
ngOnDestroy() {
111+
override ngOnDestroy() {
112+
super.ngOnDestroy();
113+
107114
if (this._animationTimer !== null) {
108115
clearTimeout(this._animationTimer);
109116
}
@@ -177,7 +184,6 @@ export class MatDialogContainer extends _MatDialogContainerBase implements OnDes
177184
*/
178185
private _finishDialogClose = () => {
179186
this._clearAnimationClasses();
180-
this._restoreFocus();
181187
this._animationStateChanged.emit({state: 'closed', totalTime: this._closeAnimationDuration});
182188
};
183189

src/material-experimental/mdc-dialog/dialog-content-directives.ts

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
Optional,
1616
SimpleChanges,
1717
} from '@angular/core';
18-
import {_closeDialogVia} from '@angular/material/dialog';
1918

2019
import {MatDialog} from './dialog';
2120
import {MatDialogRef} from './dialog-ref';
@@ -79,11 +78,9 @@ export class MatDialogClose implements OnInit, OnChanges {
7978
// result in incorrect origins. Most of the time, close buttons will be auto focused in the
8079
// dialog, and therefore clicking the button won't result in a focus change. This means that
8180
// the FocusMonitor won't detect any origin change, and will always output `program`.
82-
_closeDialogVia(
83-
this.dialogRef,
84-
event.screenX === 0 && event.screenY === 0 ? 'keyboard' : 'mouse',
85-
this.dialogResult,
86-
);
81+
this.dialogRef.close(this.dialogResult, {
82+
focusOrigin: event.screenX === 0 && event.screenY === 0 ? 'keyboard' : 'mouse',
83+
});
8784
}
8885
}
8986

src/material-experimental/mdc-dialog/dialog-ref.ts

Lines changed: 1 addition & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,22 +6,9 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9-
import {OverlayRef} from '@angular/cdk/overlay';
109
import {MatDialogRef as NonMdcDialogRef} from '@angular/material/dialog';
11-
import {MatDialogContainer} from './dialog-container';
12-
13-
// Counter for unique dialog ids.
14-
let uniqueId = 0;
1510

1611
/**
1712
* Reference to a dialog opened via the MatDialog service.
1813
*/
19-
export class MatDialogRef<T, R = any> extends NonMdcDialogRef<T, R> {
20-
constructor(
21-
overlayRef: OverlayRef,
22-
containerInstance: MatDialogContainer,
23-
id: string = `mat-mdc-dialog-${uniqueId++}`,
24-
) {
25-
super(overlayRef, containerInstance, id);
26-
}
27-
}
14+
export class MatDialogRef<T, R = any> extends NonMdcDialogRef<T, R> {}

src/material-experimental/mdc-dialog/dialog.spec.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,7 @@ describe('MDC-based MatDialog', () => {
13251325

13261326
tick(500);
13271327
viewContainerFixture.detectChanges();
1328+
flushMicrotasks();
13281329
expect(lastFocusOrigin!).withContext('Expected the trigger button to be blurred').toBeNull();
13291330

13301331
dispatchKeyboardEvent(document.body, 'keydown', ESCAPE);
@@ -1359,6 +1360,7 @@ describe('MDC-based MatDialog', () => {
13591360

13601361
tick(500);
13611362
viewContainerFixture.detectChanges();
1363+
flushMicrotasks();
13621364
expect(lastFocusOrigin!).withContext('Expected the trigger button to be blurred').toBeNull();
13631365

13641366
const backdrop = overlayContainerElement.querySelector(
@@ -1395,6 +1397,7 @@ describe('MDC-based MatDialog', () => {
13951397

13961398
tick(500);
13971399
viewContainerFixture.detectChanges();
1400+
flushMicrotasks();
13981401
expect(lastFocusOrigin!).withContext('Expected the trigger button to be blurred').toBeNull();
13991402

14001403
const closeButton = overlayContainerElement.querySelector(
@@ -1434,6 +1437,7 @@ describe('MDC-based MatDialog', () => {
14341437

14351438
tick(500);
14361439
viewContainerFixture.detectChanges();
1440+
flushMicrotasks();
14371441
expect(lastFocusOrigin!).withContext('Expected the trigger button to be blurred').toBeNull();
14381442

14391443
const closeButton = overlayContainerElement.querySelector(

src/material-experimental/mdc-dialog/dialog.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,18 @@
88

99
import {Overlay, OverlayContainer, ScrollStrategy} from '@angular/cdk/overlay';
1010
import {Location} from '@angular/common';
11-
import {Inject, Injectable, InjectionToken, Injector, Optional, SkipSelf} from '@angular/core';
11+
import {
12+
ANIMATION_MODULE_TYPE,
13+
Inject,
14+
Injectable,
15+
InjectionToken,
16+
Injector,
17+
Optional,
18+
SkipSelf,
19+
} from '@angular/core';
1220
import {_MatDialogBase, MatDialogConfig} from '@angular/material/dialog';
1321
import {MatDialogContainer} from './dialog-container';
1422
import {MatDialogRef} from './dialog-ref';
15-
import {ANIMATION_MODULE_TYPE} from '@angular/platform-browser/animations';
1623

1724
/** Injection token that can be used to access the data that was passed in to a dialog. */
1825
export const MAT_DIALOG_DATA = new InjectionToken<any>('MatMdcDialogData');
@@ -46,6 +53,8 @@ export const MAT_DIALOG_SCROLL_STRATEGY_PROVIDER = {
4653
*/
4754
@Injectable()
4855
export class MatDialog extends _MatDialogBase<MatDialogContainer> {
56+
protected readonly _idPrefix = 'mat-mdc-dialog-';
57+
4958
constructor(
5059
overlay: Overlay,
5160
injector: Injector,
@@ -57,6 +66,10 @@ export class MatDialog extends _MatDialogBase<MatDialogContainer> {
5766
@Optional() @Inject(MAT_DIALOG_DEFAULT_OPTIONS) defaultOptions: MatDialogConfig,
5867
@Inject(MAT_DIALOG_SCROLL_STRATEGY) scrollStrategy: any,
5968
@Optional() @SkipSelf() parentDialog: MatDialog,
69+
/**
70+
* @deprecated No longer used. To be removed.
71+
* @breaking-change 15.0.0
72+
*/
6073
overlayContainer: OverlayContainer,
6174
/**
6275
* @deprecated No longer used. To be removed.

src/material-experimental/mdc-dialog/module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import {DialogModule} from '@angular/cdk/dialog';
910
import {OverlayModule} from '@angular/cdk/overlay';
1011
import {PortalModule} from '@angular/cdk/portal';
1112
import {NgModule} from '@angular/core';
@@ -20,7 +21,7 @@ import {
2021
} from './dialog-content-directives';
2122

2223
@NgModule({
23-
imports: [OverlayModule, PortalModule, MatCommonModule],
24+
imports: [DialogModule, OverlayModule, PortalModule, MatCommonModule],
2425
exports: [
2526
MatDialogContainer,
2627
MatDialogClose,

src/material-experimental/mdc-dialog/public-api.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ export {
1717
MatDialogState,
1818
MatDialogConfig,
1919
matDialogAnimations,
20-
throwMatDialogContentAlreadyAttachedError,
2120
DialogRole,
2221
DialogPosition,
2322
MAT_DIALOG_SCROLL_STRATEGY_FACTORY,

src/material/dialog/BUILD.bazel

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ ng_module(
2323
"//src:dev_mode_types",
2424
"//src/cdk/a11y",
2525
"//src/cdk/bidi",
26+
"//src/cdk/dialog",
2627
"//src/cdk/keycodes",
2728
"//src/cdk/overlay",
2829
"//src/cdk/platform",

src/material/dialog/dialog-config.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -112,10 +112,14 @@ export class MatDialogConfig<D = any> {
112112
autoFocus?: AutoFocusTarget | string | boolean = 'first-tabbable';
113113

114114
/**
115-
* Whether the dialog should restore focus to the
116-
* previously-focused element, after it's closed.
115+
* Whether the dialog should restore focus to the previously-focused element upon closing.
116+
* Has the following behavior based on the type that is passed in:
117+
* - `boolean` - when true, will return focus to the element that was focused before the dialog
118+
* was opened, otherwise won't restore focus at all.
119+
* - `string` - focus will be restored to the first element that matches the CSS selector.
120+
* - `HTMLElement` - focus will be restored to the specific element.
117121
*/
118-
restoreFocus?: boolean = true;
122+
restoreFocus?: boolean | string | HTMLElement = true;
119123

120124
/** Whether to wait for the opening animation to finish before trapping focus. */
121125
delayFocusTrap?: boolean = true;

0 commit comments

Comments
 (0)