Skip to content

Commit 9be998a

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. (cherry picked from commit ef6ffb4)
1 parent bddc717 commit 9be998a

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)