Skip to content

Commit ebf8407

Browse files
committed
fix(dialog): capture previously focused element immediately
Captures the previously-focused element immediately, instead of waiting until the animation is done. This fixes a regression from #3774, because if we wait for the animation to finish, the focus might have shifted, or the element could have been disabled.
1 parent f40296e commit ebf8407

File tree

1 file changed

+20
-3
lines changed

1 file changed

+20
-3
lines changed

src/lib/dialog/dialog-container.ts

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ import {
88
Renderer,
99
ElementRef,
1010
EventEmitter,
11+
Inject,
12+
Optional,
1113
} from '@angular/core';
1214
import {
1315
animate,
@@ -17,6 +19,7 @@ import {
1719
transition,
1820
AnimationEvent,
1921
} from '@angular/animations';
22+
import {DOCUMENT} from '@angular/platform-browser';
2023
import {BasePortalHost, ComponentPortal, PortalHostDirective, TemplatePortal} from '../core';
2124
import {MdDialogConfig} from './dialog-config';
2225
import {MdDialogContentAlreadyAttachedError} from './dialog-errors';
@@ -64,6 +67,9 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
6467
/** Element that was focused before the dialog was opened. Save this to restore upon close. */
6568
private _elementFocusedBeforeDialogWasOpened: HTMLElement = null;
6669

70+
/** Reference to the global document object. */
71+
private _document: Document|Document;
72+
6773
/** The dialog configuration. */
6874
dialogConfig: MdDialogConfig;
6975

@@ -77,9 +83,11 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
7783
private _ngZone: NgZone,
7884
private _renderer: Renderer,
7985
private _elementRef: ElementRef,
80-
private _focusTrapFactory: FocusTrapFactory) {
86+
private _focusTrapFactory: FocusTrapFactory,
87+
@Optional() @Inject(DOCUMENT) _document: any) {
8188

8289
super();
90+
this._document = _document;
8391
}
8492

8593
/**
@@ -91,6 +99,7 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
9199
throw new MdDialogContentAlreadyAttachedError();
92100
}
93101

102+
this._savePreviouslyFocusedElement();
94103
return this._portalHost.attachComponentPortal(portal);
95104
}
96105

@@ -103,12 +112,12 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
103112
throw new MdDialogContentAlreadyAttachedError();
104113
}
105114

115+
this._savePreviouslyFocusedElement();
106116
return this._portalHost.attachTemplatePortal(portal);
107117
}
108118

109119
/**
110120
* Moves the focus inside the focus trap.
111-
* @private
112121
*/
113122
private _trapFocus() {
114123
if (!this._focusTrap) {
@@ -118,10 +127,18 @@ export class MdDialogContainer extends BasePortalHost implements OnDestroy {
118127
// If were to attempt to focus immediately, then the content of the dialog would not yet be
119128
// ready in instances where change detection has to run first. To deal with this, we simply
120129
// wait for the microtask queue to be empty.
121-
this._elementFocusedBeforeDialogWasOpened = document.activeElement as HTMLElement;
122130
this._focusTrap.focusFirstTabbableElementWhenReady();
123131
}
124132

133+
/**
134+
* Saves a reference to the element that was focused before the dialog was opened.
135+
*/
136+
private _savePreviouslyFocusedElement() {
137+
if (this._document) {
138+
this._elementFocusedBeforeDialogWasOpened = this._document.activeElement as HTMLElement;
139+
}
140+
}
141+
125142
/**
126143
* Kicks off the leave animation.
127144
* @docs-private

0 commit comments

Comments
 (0)