diff --git a/src/cdk/scrolling/virtual-for-of.ts b/src/cdk/scrolling/virtual-for-of.ts index 0a2def6a6557..6700bcfb147e 100644 --- a/src/cdk/scrolling/virtual-for-of.ts +++ b/src/cdk/scrolling/virtual-for-of.ts @@ -199,7 +199,9 @@ export class CdkVirtualForOf }); this._viewport.renderedRangeStream.pipe(takeUntil(this._destroyed)).subscribe(range => { this._renderedRange = range; - ngZone.run(() => this.viewChange.next(this._renderedRange)); + if (this.viewChange.observers.length) { + ngZone.run(() => this.viewChange.next(this._renderedRange)); + } this._onRenderedDataChange(); }); this._viewport.attach(this); diff --git a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts index 71202b01eb6f..97cabe8b58e6 100644 --- a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts +++ b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts @@ -15,6 +15,7 @@ import { ViewEncapsulation, Directive, ViewContainerRef, + ApplicationRef, } from '@angular/core'; import { waitForAsync, @@ -786,6 +787,43 @@ describe('CdkVirtualScrollViewport', () => { } }).not.toThrow(); })); + + describe('viewChange change detection behavior', () => { + let appRef: ApplicationRef; + + beforeEach(inject([ApplicationRef], (ar: ApplicationRef) => { + appRef = ar; + })); + + it('should not run change detection if there are no viewChange listeners', fakeAsync(() => { + finishInit(fixture); + testComponent.items = Array(10).fill(0); + fixture.detectChanges(); + flush(); + + spyOn(appRef, 'tick'); + + viewport.scrollToIndex(5); + triggerScroll(viewport); + + expect(appRef.tick).not.toHaveBeenCalled(); + })); + + it('should run change detection if there are any viewChange listeners', fakeAsync(() => { + testComponent.virtualForOf.viewChange.subscribe(); + finishInit(fixture); + testComponent.items = Array(10).fill(0); + fixture.detectChanges(); + flush(); + + spyOn(appRef, 'tick'); + + viewport.scrollToIndex(5); + triggerScroll(viewport); + + expect(appRef.tick).toHaveBeenCalledTimes(1); + })); + }); }); describe('with RTL direction', () => {