Skip to content

Commit c8c7068

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 bf17e32 commit c8c7068

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

Comments
 (0)