diff --git a/libs/cdk/render-strategies/src/lib/concurrent-strategies.ts b/libs/cdk/render-strategies/src/lib/concurrent-strategies.ts index d624c9e49..d1ad362c9 100644 --- a/libs/cdk/render-strategies/src/lib/concurrent-strategies.ts +++ b/libs/cdk/render-strategies/src/lib/concurrent-strategies.ts @@ -1,4 +1,4 @@ -import { NgZone } from '@angular/core'; +import { NgZone, PendingTasks } from '@angular/core'; import { coalescingManager, coalescingObj } from '@rx-angular/cdk/coalescing'; import { cancelCallback, @@ -17,6 +17,14 @@ import { // set default to 60fps forceFrameRate(60); +let pendingTasks: PendingTasks | undefined; + +export function setPendingTasks(p: PendingTasks) { + if (!pendingTasks) { + pendingTasks = p; + } +} + const immediateStrategy: RxStrategyCredentials = { name: 'immediate', work: (cdRef) => cdRef.detectChanges(), @@ -27,7 +35,7 @@ const immediateStrategy: RxStrategyCredentials = { ngZone, priority: PriorityLevel.ImmediatePriority, scope, - }) + }), ); }, }; @@ -42,7 +50,7 @@ const userBlockingStrategy: RxStrategyCredentials = { ngZone, priority: PriorityLevel.UserBlockingPriority, scope, - }) + }), ); }, }; @@ -57,7 +65,7 @@ const normalStrategy: RxStrategyCredentials = { ngZone, priority: PriorityLevel.NormalPriority, scope, - }) + }), ); }, }; @@ -72,7 +80,7 @@ const lowStrategy: RxStrategyCredentials = { ngZone, priority: PriorityLevel.LowPriority, scope, - }) + }), ); }, }; @@ -87,7 +95,7 @@ const idleStrategy: RxStrategyCredentials = { ngZone, priority: PriorityLevel.IdlePriority, scope, - }) + }), ); }, }; @@ -99,7 +107,7 @@ function scheduleOnQueue( scope: coalescingObj; delay?: number; ngZone: NgZone; - } + }, ): MonoTypeOperatorFunction { const scope = (options.scope as Record) || {}; return (o$: Observable): Observable => @@ -108,21 +116,24 @@ function scheduleOnQueue( switchMap((v) => new Observable((subscriber) => { coalescingManager.add(scope); + const cleanup = pendingTasks?.add(); const task = scheduleCallback( options.priority, () => { work(); coalescingManager.remove(scope); subscriber.next(v); + cleanup?.(); }, - { delay: options.delay, ngZone: options.ngZone } + { delay: options.delay, ngZone: options.ngZone }, ); return () => { coalescingManager.remove(scope); cancelCallback(task); + cleanup?.(); }; - }).pipe(mapTo(v)) - ) + }).pipe(mapTo(v)), + ), ); } diff --git a/libs/cdk/render-strategies/src/lib/strategy-provider.service.ts b/libs/cdk/render-strategies/src/lib/strategy-provider.service.ts index fbd1fb6da..fe7727221 100644 --- a/libs/cdk/render-strategies/src/lib/strategy-provider.service.ts +++ b/libs/cdk/render-strategies/src/lib/strategy-provider.service.ts @@ -1,9 +1,11 @@ import { ChangeDetectorRef, Inject, + inject, Injectable, NgZone, Optional, + PendingTasks, } from '@angular/core'; import { BehaviorSubject, @@ -12,6 +14,7 @@ import { Observable, } from 'rxjs'; import { map, shareReplay, switchMap, takeUntil } from 'rxjs/operators'; +import { setPendingTasks } from './concurrent-strategies'; import { mergeDefaultConfig, RX_RENDER_STRATEGIES_CONFIG, @@ -108,7 +111,7 @@ export class RxStrategyProvider { */ set primaryStrategy(strategyName: RxStrategyNames) { this._primaryStrategy$.next( - >>this.strategies[strategyName] + >>this.strategies[strategyName], ); } @@ -131,7 +134,7 @@ export class RxStrategyProvider { */ readonly strategyNames$ = this.strategies$.pipe( map((strategies) => Object.values(strategies).map((s) => s.name)), - shareReplay({ bufferSize: 1, refCount: true }) + shareReplay({ bufferSize: 1, refCount: true }), ); /** @@ -140,8 +143,9 @@ export class RxStrategyProvider { constructor( @Optional() @Inject(RX_RENDER_STRATEGIES_CONFIG) - cfg: RxRenderStrategiesConfig + cfg: RxRenderStrategiesConfig, ) { + setPendingTasks(inject(PendingTasks)); this._cfg = mergeDefaultConfig(cfg); this._strategies$.next(this._cfg.customStrategies as any); this.primaryStrategy = this.config.primaryStrategy; @@ -165,7 +169,7 @@ export class RxStrategyProvider { */ scheduleWith( work: (v?: R) => void, - options?: ScheduleOnStrategyOptions + options?: ScheduleOnStrategyOptions, ): MonoTypeOperatorFunction { const strategy = this.strategies[options?.strategy || this.primaryStrategy]; const scope = options?.scope || {}; @@ -180,9 +184,9 @@ export class RxStrategyProvider { (_v) => { _work(_v); }, - { scope, ngZone } - ) - ) + { scope, ngZone }, + ), + ), ); } @@ -202,7 +206,7 @@ export class RxStrategyProvider { */ schedule( work: () => R, - options?: ScheduleOnStrategyOptions + options?: ScheduleOnStrategyOptions, ): Observable { const strategy = this.strategies[options?.strategy || this.primaryStrategy]; const scope = options?.scope || {}; @@ -215,7 +219,7 @@ export class RxStrategyProvider { () => { returnVal = _work(); }, - { scope, ngZone } + { scope, ngZone }, ).pipe(map(() => returnVal)); } @@ -236,7 +240,7 @@ export class RxStrategyProvider { options?: ScheduleOnStrategyOptions & { afterCD?: () => void; abortCtrl?: AbortController; - } + }, ): AbortController { const strategy = this.strategies[options?.strategy || this.primaryStrategy]; const scope = options?.scope || cdRef; @@ -254,7 +258,7 @@ export class RxStrategyProvider { () => { work(); }, - { scope, ngZone } + { scope, ngZone }, ) .pipe(takeUntil(fromEvent(abC.signal, 'abort'))) .subscribe(); @@ -264,7 +268,7 @@ export class RxStrategyProvider { function getWork( work: (args?: any) => T, - patchZone?: false | NgZone + patchZone?: false | NgZone, ): (args?: any) => T { let _work = work; if (patchZone) { diff --git a/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-element.directive.ts b/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-element.directive.ts index 4251eccd1..b941dee52 100644 --- a/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-element.directive.ts +++ b/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-element.directive.ts @@ -10,7 +10,6 @@ import { unpatchedScroll } from './util'; useExisting: RxVirtualScrollElementDirective, }, ], - // eslint-disable-next-line @angular-eslint/no-host-metadata-property host: { class: 'rx-virtual-scroll-element', }, diff --git a/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-viewport.component.ts b/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-viewport.component.ts index d1cbfd9c7..eda09366c 100644 --- a/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-viewport.component.ts +++ b/libs/template/experimental/virtual-scrolling/src/lib/virtual-scroll-viewport.component.ts @@ -73,7 +73,6 @@ const NG_DEV_MODE = typeof ngDevMode === 'undefined' || !!ngDevMode; ], encapsulation: ViewEncapsulation.None, styleUrls: ['./virtual-scroll-viewport.component.scss'], - // eslint-disable-next-line @angular-eslint/no-host-metadata-property host: { class: 'rx-virtual-scroll-viewport', },