@@ -305,6 +305,13 @@ export class MatFormField
305305 private _explicitFormFieldControl : MatFormFieldControl < any > ;
306306 private _needsOutlineLabelOffsetUpdate = false ;
307307
308+ /**
309+ * Cached shadow root that the element is placed in. `null` means that the element isn't in
310+ * the shadow DOM and `undefined` means that it hasn't been resolved yet. Should be read via
311+ * `_getShadowRoot`, not directly.
312+ */
313+ private _cachedShadowRoot : ShadowRoot | null | undefined ;
314+
308315 private _injector = inject ( Injector ) ;
309316
310317 constructor (
@@ -709,7 +716,21 @@ export class MatFormField
709716 rootNode !== element &&
710717 // If the rootNode is the document we need to make sure that the element is visible
711718 ( ( rootNode === document && element . offsetParent !== null ) ||
712- rootNode === _getShadowRoot ( element ) )
719+ rootNode === this . _getShadowRoot ( ) )
713720 ) ;
714721 }
722+
723+ /**
724+ * Lazily resolves and returns the shadow root of the element. We do this in a function, rather
725+ * than saving it in property directly on init, because we want to resolve it as late as possible
726+ * in order to ensure that the element has been moved into the shadow DOM. Doing it inside the
727+ * constructor might be too early if the element is inside of something like `ngFor` or `ngIf`.
728+ */
729+ private _getShadowRoot ( ) : ShadowRoot | null {
730+ if ( this . _cachedShadowRoot === undefined ) {
731+ this . _cachedShadowRoot = _getShadowRoot ( this . _elementRef . nativeElement ) ;
732+ }
733+
734+ return this . _cachedShadowRoot ;
735+ }
715736}
0 commit comments