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