@@ -316,6 +316,13 @@ export class MatFormField
316316 private _explicitFormFieldControl : MatFormFieldControl < any > ;
317317 private _needsOutlineLabelOffsetUpdate = false ;
318318
319+ /**
320+ * Cached shadow root that the element is placed in. `null` means that the element isn't in
321+ * the shadow DOM and `undefined` means that it hasn't been resolved yet. Should be read via
322+ * `_getShadowRoot`, not directly.
323+ */
324+ private _cachedShadowRoot : ShadowRoot | null | undefined ;
325+
319326 private _injector = inject ( Injector ) ;
320327
321328 constructor (
@@ -720,7 +727,21 @@ export class MatFormField
720727 rootNode !== element &&
721728 // If the rootNode is the document we need to make sure that the element is visible
722729 ( ( rootNode === document && element . offsetParent !== null ) ||
723- rootNode === _getShadowRoot ( element ) )
730+ rootNode === this . _getShadowRoot ( ) )
724731 ) ;
725732 }
733+
734+ /**
735+ * Lazily resolves and returns the shadow root of the element. We do this in a function, rather
736+ * than saving it in property directly on init, because we want to resolve it as late as possible
737+ * in order to ensure that the element has been moved into the shadow DOM. Doing it inside the
738+ * constructor might be too early if the element is inside of something like `ngFor` or `ngIf`.
739+ */
740+ private _getShadowRoot ( ) : ShadowRoot | null {
741+ if ( this . _cachedShadowRoot === undefined ) {
742+ this . _cachedShadowRoot = _getShadowRoot ( this . _elementRef . nativeElement ) ;
743+ }
744+
745+ return this . _cachedShadowRoot ;
746+ }
726747}
0 commit comments