Skip to content

Commit 94a9fa9

Browse files
committed
fix(cdk/dialog): resolve hydration error in focus trap
Disables focus traps on the server, because they insert DOM nodes that can throw off hydration. (cherry picked from commit 230bdb5)
1 parent 5e2d13b commit 94a9fa9

File tree

1 file changed

+12
-8
lines changed

1 file changed

+12
-8
lines changed

src/cdk/dialog/dialog-container.ts

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import {
1414
InteractivityChecker,
1515
} from '@angular/cdk/a11y';
1616
import {OverlayRef} from '@angular/cdk/overlay';
17-
import {_getFocusedElementPierceShadowDom} from '@angular/cdk/platform';
17+
import {Platform, _getFocusedElementPierceShadowDom} from '@angular/cdk/platform';
1818
import {
1919
BasePortalOutlet,
2020
CdkPortalOutlet,
@@ -36,6 +36,7 @@ import {
3636
Optional,
3737
ViewChild,
3838
ViewEncapsulation,
39+
inject,
3940
} from '@angular/core';
4041
import {DialogConfig} from './dialog-config';
4142

@@ -72,13 +73,14 @@ export class CdkDialogContainer<C extends DialogConfig = DialogConfig>
7273
extends BasePortalOutlet
7374
implements OnDestroy
7475
{
76+
private _platform = inject(Platform);
7577
protected _document: Document;
7678

7779
/** The portal outlet inside of this container into which the dialog content will be loaded. */
7880
@ViewChild(CdkPortalOutlet, {static: true}) _portalOutlet: CdkPortalOutlet;
7981

8082
/** The class that traps and manages focus within the dialog. */
81-
private _focusTrap: FocusTrap;
83+
private _focusTrap: FocusTrap | null = null;
8284

8385
/** Element that was focused before the dialog was opened. Save this to restore upon close. */
8486
private _elementFocusedBeforeDialogWasOpened: HTMLElement | null = null;
@@ -248,7 +250,7 @@ export class CdkDialogContainer<C extends DialogConfig = DialogConfig>
248250
break;
249251
case true:
250252
case 'first-tabbable':
251-
this._focusTrap.focusInitialElementWhenReady().then(focusedSuccessfully => {
253+
this._focusTrap?.focusInitialElementWhenReady().then(focusedSuccessfully => {
252254
// If we weren't able to find a focusable element in the dialog, then focus the dialog
253255
// container instead.
254256
if (!focusedSuccessfully) {
@@ -328,12 +330,14 @@ export class CdkDialogContainer<C extends DialogConfig = DialogConfig>
328330

329331
/** Sets up the focus trap. */
330332
private _initializeFocusTrap() {
331-
this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
333+
if (this._platform.isBrowser) {
334+
this._focusTrap = this._focusTrapFactory.create(this._elementRef.nativeElement);
332335

333-
// Save the previously focused element. This element will be re-focused
334-
// when the dialog closes.
335-
if (this._document) {
336-
this._elementFocusedBeforeDialogWasOpened = _getFocusedElementPierceShadowDom();
336+
// Save the previously focused element. This element will be re-focused
337+
// when the dialog closes.
338+
if (this._document) {
339+
this._elementFocusedBeforeDialogWasOpened = _getFocusedElementPierceShadowDom();
340+
}
337341
}
338342
}
339343

0 commit comments

Comments
 (0)