@@ -101,7 +101,6 @@ export function MAT_DRAWER_DEFAULT_AUTOSIZE_FACTORY(): boolean {
101
101
'class' : 'mat-drawer-content' ,
102
102
'[style.margin-left.px]' : '_container._contentMargins.left' ,
103
103
'[style.margin-right.px]' : '_container._contentMargins.right' ,
104
- 'ngSkipHydration' : '' ,
105
104
} ,
106
105
changeDetection : ChangeDetectionStrategy . OnPush ,
107
106
encapsulation : ViewEncapsulation . None ,
@@ -152,15 +151,14 @@ export class MatDrawerContent extends CdkScrollable implements AfterContentInit
152
151
'[@transform]' : '_animationState' ,
153
152
'(@transform.start)' : '_animationStarted.next($event)' ,
154
153
'(@transform.done)' : '_animationEnd.next($event)' ,
155
- 'ngSkipHydration' : '' ,
156
154
} ,
157
155
changeDetection : ChangeDetectionStrategy . OnPush ,
158
156
encapsulation : ViewEncapsulation . None ,
159
157
standalone : true ,
160
158
imports : [ CdkScrollable ] ,
161
159
} )
162
160
export class MatDrawer implements AfterViewInit , AfterContentChecked , OnDestroy {
163
- private _focusTrap : FocusTrap ;
161
+ private _focusTrap : FocusTrap | null = null ;
164
162
private _elementFocusedBeforeDrawerWasOpened : HTMLElement | null = null ;
165
163
166
164
/** Whether the drawer is initialized. Used for disabling the initial animation. */
@@ -480,14 +478,19 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
480
478
481
479
ngAfterViewInit ( ) {
482
480
this . _isAttached = true ;
483
- this . _focusTrap = this . _focusTrapFactory . create ( this . _elementRef . nativeElement ) ;
484
- this . _updateFocusTrapState ( ) ;
485
481
486
482
// Only update the DOM position when the sidenav is positioned at
487
483
// the end since we project the sidenav before the content by default.
488
484
if ( this . _position === 'end' ) {
489
485
this . _updatePositionInParent ( 'end' ) ;
490
486
}
487
+
488
+ // Needs to happen after the position is updated
489
+ // so the focus trap anchors are in the right place.
490
+ if ( this . _platform . isBrowser ) {
491
+ this . _focusTrap = this . _focusTrapFactory . create ( this . _elementRef . nativeElement ) ;
492
+ this . _updateFocusTrapState ( ) ;
493
+ }
491
494
}
492
495
493
496
ngAfterContentChecked ( ) {
@@ -501,10 +504,7 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
501
504
}
502
505
503
506
ngOnDestroy ( ) {
504
- if ( this . _focusTrap ) {
505
- this . _focusTrap . destroy ( ) ;
506
- }
507
-
507
+ this . _focusTrap ?. destroy ( ) ;
508
508
this . _anchor ?. remove ( ) ;
509
509
this . _anchor = null ;
510
510
this . _animationStarted . complete ( ) ;
@@ -610,7 +610,12 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
610
610
* matches the tab order. We also need to be able to move it back to `start` if the sidenav
611
611
* started off as `end` and was changed to `start`.
612
612
*/
613
- private _updatePositionInParent ( newPosition : 'start' | 'end' ) {
613
+ private _updatePositionInParent ( newPosition : 'start' | 'end' ) : void {
614
+ // Don't move the DOM node around on the server, because it can throw off hydration.
615
+ if ( ! this . _platform . isBrowser ) {
616
+ return ;
617
+ }
618
+
614
619
const element = this . _elementRef . nativeElement ;
615
620
const parent = element . parentNode ! ;
616
621
@@ -641,7 +646,6 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
641
646
host : {
642
647
'class' : 'mat-drawer-container' ,
643
648
'[class.mat-drawer-container-explicit-backdrop]' : '_backdropOverride' ,
644
- 'ngSkipHydration' : '' ,
645
649
} ,
646
650
changeDetection : ChangeDetectionStrategy . OnPush ,
647
651
encapsulation : ViewEncapsulation . None ,
0 commit comments