@@ -101,7 +101,6 @@ export function MAT_DRAWER_DEFAULT_AUTOSIZE_FACTORY(): boolean {
101101 'class' : 'mat-drawer-content' ,
102102 '[style.margin-left.px]' : '_container._contentMargins.left' ,
103103 '[style.margin-right.px]' : '_container._contentMargins.right' ,
104- 'ngSkipHydration' : '' ,
105104 } ,
106105 changeDetection : ChangeDetectionStrategy . OnPush ,
107106 encapsulation : ViewEncapsulation . None ,
@@ -152,15 +151,14 @@ export class MatDrawerContent extends CdkScrollable implements AfterContentInit
152151 '[@transform]' : '_animationState' ,
153152 '(@transform.start)' : '_animationStarted.next($event)' ,
154153 '(@transform.done)' : '_animationEnd.next($event)' ,
155- 'ngSkipHydration' : '' ,
156154 } ,
157155 changeDetection : ChangeDetectionStrategy . OnPush ,
158156 encapsulation : ViewEncapsulation . None ,
159157 standalone : true ,
160158 imports : [ CdkScrollable ] ,
161159} )
162160export class MatDrawer implements AfterViewInit , AfterContentChecked , OnDestroy {
163- private _focusTrap : FocusTrap ;
161+ private _focusTrap : FocusTrap | null = null ;
164162 private _elementFocusedBeforeDrawerWasOpened : HTMLElement | null = null ;
165163
166164 /** Whether the drawer is initialized. Used for disabling the initial animation. */
@@ -480,14 +478,19 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
480478
481479 ngAfterViewInit ( ) {
482480 this . _isAttached = true ;
483- this . _focusTrap = this . _focusTrapFactory . create ( this . _elementRef . nativeElement ) ;
484- this . _updateFocusTrapState ( ) ;
485481
486482 // Only update the DOM position when the sidenav is positioned at
487483 // the end since we project the sidenav before the content by default.
488484 if ( this . _position === 'end' ) {
489485 this . _updatePositionInParent ( 'end' ) ;
490486 }
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+ }
491494 }
492495
493496 ngAfterContentChecked ( ) {
@@ -501,10 +504,7 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
501504 }
502505
503506 ngOnDestroy ( ) {
504- if ( this . _focusTrap ) {
505- this . _focusTrap . destroy ( ) ;
506- }
507-
507+ this . _focusTrap ?. destroy ( ) ;
508508 this . _anchor ?. remove ( ) ;
509509 this . _anchor = null ;
510510 this . _animationStarted . complete ( ) ;
@@ -610,7 +610,12 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
610610 * matches the tab order. We also need to be able to move it back to `start` if the sidenav
611611 * started off as `end` and was changed to `start`.
612612 */
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+
614619 const element = this . _elementRef . nativeElement ;
615620 const parent = element . parentNode ! ;
616621
@@ -641,7 +646,6 @@ export class MatDrawer implements AfterViewInit, AfterContentChecked, OnDestroy
641646 host : {
642647 'class' : 'mat-drawer-container' ,
643648 '[class.mat-drawer-container-explicit-backdrop]' : '_backdropOverride' ,
644- 'ngSkipHydration' : '' ,
645649 } ,
646650 changeDetection : ChangeDetectionStrategy . OnPush ,
647651 encapsulation : ViewEncapsulation . None ,
0 commit comments