Skip to content

Commit 2c6befe

Browse files
perf(material/form-field): add caching for shadow root
Add caching for shadow root so it doesn't have to be resolved each time
1 parent 5264fd2 commit 2c6befe

File tree

1 file changed

+22
-1
lines changed

1 file changed

+22
-1
lines changed

src/material/form-field/form-field.ts

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)