Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 09270f9

Browse files
committed
fix(template): improve DataSource lifecycle management in RxVirtualFor
- Renamed potentialSignalOrObservable to potentialSignalOrObservableOrDataSource - Move DataSource disconnect from subscription to ngOnDestroy lifecycle - Add disconnectDataSource() method for centralized cleanup logic - Ensure disconnect and cleanup of previous data source on data source input changes to prevent memory leaks
1 parent f9b9bdd commit 09270f9

File tree

1 file changed

+32
-15
lines changed

1 file changed

+32
-15
lines changed

libs/template/experimental/virtual-scrolling/src/lib/virtual-for.directive.ts

Lines changed: 32 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -216,6 +216,11 @@ export class RxVirtualFor<T, U extends NgIterable<T> = NgIterable<T>>
216216
optional: true,
217217
});
218218

219+
/** @internal */
220+
private connectedDataSource?: DataSource<T>;
221+
/** @internal */
222+
private collectionViewer?: CollectionViewer;
223+
219224
/** @internal */
220225
private _differ?: IterableDiffer<T>;
221226

@@ -237,46 +242,49 @@ export class RxVirtualFor<T, U extends NgIterable<T> = NgIterable<T>>
237242
* [hero]="hero"></app-hero>
238243
* </rx-virtual-scroll-viewport>
239244
*
240-
* @param potentialSignalOrObservable
245+
* @param potentialSignalOrObservableOrDataSource
241246
*/
242247
@Input()
243248
set rxVirtualForOf(
244-
potentialSignalOrObservable:
249+
potentialSignalOrObservableOrDataSource:
245250
| Observable<(U & NgIterable<T>) | undefined | null>
246251
| Signal<(U & NgIterable<T>) | undefined | null>
247252
| DataSource<T>
248253
| (U & NgIterable<T>)
249254
| null
250255
| undefined,
251256
) {
252-
if (isSignal(potentialSignalOrObservable)) {
257+
if (isSignal(potentialSignalOrObservableOrDataSource)) {
253258
this.staticValue = undefined;
254259
this.renderStatic = false;
255260
this.observables$.next(
256-
toObservable(potentialSignalOrObservable, { injector: this.injector }),
261+
toObservable(potentialSignalOrObservableOrDataSource, {
262+
injector: this.injector,
263+
}),
257264
);
258-
} else if (this.isDataSource(potentialSignalOrObservable)) {
265+
} else if (this.isDataSource(potentialSignalOrObservableOrDataSource)) {
266+
this.disconnectDataSource();
267+
259268
this.staticValue = undefined;
260269
this.renderStatic = false;
261270

262271
const collectionViewer: CollectionViewer = {
263272
viewChange: this.scrollStrategy.renderedRange$,
264273
};
265274

275+
this.collectionViewer = collectionViewer;
276+
this.connectedDataSource = potentialSignalOrObservableOrDataSource;
277+
266278
this.observables$.next(
267-
potentialSignalOrObservable.connect(collectionViewer),
279+
potentialSignalOrObservableOrDataSource.connect(collectionViewer),
268280
);
269-
270-
this._destroy$.pipe(take(1)).subscribe(() => {
271-
potentialSignalOrObservable.disconnect(collectionViewer);
272-
});
273-
} else if (!isObservable(potentialSignalOrObservable)) {
274-
this.staticValue = potentialSignalOrObservable;
281+
} else if (!isObservable(potentialSignalOrObservableOrDataSource)) {
282+
this.staticValue = potentialSignalOrObservableOrDataSource;
275283
this.renderStatic = true;
276284
} else {
277285
this.staticValue = undefined;
278286
this.renderStatic = false;
279-
this.observables$.next(potentialSignalOrObservable);
287+
this.observables$.next(potentialSignalOrObservableOrDataSource);
280288
}
281289
}
282290

@@ -290,8 +298,7 @@ export class RxVirtualFor<T, U extends NgIterable<T> = NgIterable<T>>
290298
| undefined,
291299
): value is DataSource<T> {
292300
return (
293-
value !== null &&
294-
value !== undefined &&
301+
value != null &&
295302
'connect' in value &&
296303
typeof value.connect === 'function' &&
297304
!(value instanceof ConnectableObservable)
@@ -677,8 +684,18 @@ export class RxVirtualFor<T, U extends NgIterable<T> = NgIterable<T>>
677684
}
678685
}
679686

687+
/** @internal */
688+
private disconnectDataSource(): void {
689+
if (this.connectedDataSource && this.collectionViewer) {
690+
this.connectedDataSource.disconnect(this.collectionViewer);
691+
this.connectedDataSource = undefined;
692+
this.collectionViewer = undefined;
693+
}
694+
}
695+
680696
/** @internal */
681697
ngOnDestroy() {
698+
this.disconnectDataSource();
682699
this._destroy$.next();
683700
this.templateManager.detach();
684701
}

0 commit comments

Comments
 (0)