Skip to content

Commit ef6ffb4

Browse files
committed
refactor: avoid clearing too much content in deferred content
The deferred content directive currently calls `ViewContainerRef.clear` which may end up removing content that the directive doesn't actually own. These changes adjust the directive so it only removes the view it inserted itself.
1 parent f440932 commit ef6ffb4

File tree

1 file changed

+23
-6
lines changed

1 file changed

+23
-6
lines changed

src/aria/deferred-content/deferred-content.ts

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ import {
1414
signal,
1515
ViewContainerRef,
1616
model,
17+
EmbeddedViewRef,
18+
OnDestroy,
1719
} from '@angular/core';
1820

1921
/**
@@ -41,25 +43,40 @@ export class DeferredContentAware {
4143
* ```
4244
*/
4345
@Directive()
44-
export class DeferredContent {
46+
export class DeferredContent implements OnDestroy {
4547
private readonly _deferredContentAware = inject(DeferredContentAware, {optional: true});
4648
private readonly _templateRef = inject(TemplateRef);
4749
private readonly _viewContainerRef = inject(ViewContainerRef);
50+
private _currentViewRef: EmbeddedViewRef<unknown> | null = null;
4851
private _isRendered = false;
4952

5053
readonly deferredContentAware = signal(this._deferredContentAware);
5154

5255
constructor() {
5356
afterRenderEffect(() => {
5457
if (this.deferredContentAware()?.contentVisible()) {
55-
if (this._isRendered) return;
56-
this._viewContainerRef.clear();
57-
this._viewContainerRef.createEmbeddedView(this._templateRef);
58-
this._isRendered = true;
58+
if (!this._isRendered) {
59+
this._destroyContent();
60+
this._currentViewRef = this._viewContainerRef.createEmbeddedView(this._templateRef);
61+
this._isRendered = true;
62+
}
5963
} else if (!this.deferredContentAware()?.preserveContent()) {
60-
this._viewContainerRef.clear();
64+
this._destroyContent();
6165
this._isRendered = false;
6266
}
6367
});
6468
}
69+
70+
ngOnDestroy(): void {
71+
this._destroyContent();
72+
}
73+
74+
private _destroyContent() {
75+
const ref = this._currentViewRef;
76+
77+
if (ref && !ref.destroyed) {
78+
ref.destroy();
79+
this._currentViewRef = null;
80+
}
81+
}
6582
}

0 commit comments

Comments
 (0)