Skip to content

Commit 5648c0b

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 c9ea129 commit 5648c0b

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
@@ -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

Comments
 (0)