diff --git a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts index cdb4c6543422..27f6e854c202 100644 --- a/src/cdk/scrolling/virtual-scroll-viewport.spec.ts +++ b/src/cdk/scrolling/virtual-scroll-viewport.spec.ts @@ -16,7 +16,15 @@ import { Directive, ViewContainerRef } from '@angular/core'; -import {async, ComponentFixture, fakeAsync, flush, inject, TestBed} from '@angular/core/testing'; +import { + async, + ComponentFixture, + fakeAsync, + flush, + inject, + TestBed, + tick, +} from '@angular/core/testing'; import {animationFrameScheduler, Subject} from 'rxjs'; @@ -74,6 +82,17 @@ describe('CdkVirtualScrollViewport', () => { expect(viewport.getViewportSize()).toBe(500); })); + it('should update the viewport size when the page viewport changes', fakeAsync(() => { + finishInit(fixture); + spyOn(viewport, 'checkViewportSize').and.callThrough(); + + dispatchFakeEvent(window, 'resize'); + fixture.detectChanges(); + tick(20); // The resize listener is debounced so we need to flush it. + + expect(viewport.checkViewportSize).toHaveBeenCalled(); + })); + it('should get the rendered range', fakeAsync(() => { finishInit(fixture); diff --git a/src/cdk/scrolling/virtual-scroll-viewport.ts b/src/cdk/scrolling/virtual-scroll-viewport.ts index 0c6a113981c6..a18194bb1876 100644 --- a/src/cdk/scrolling/virtual-scroll-viewport.ts +++ b/src/cdk/scrolling/virtual-scroll-viewport.ts @@ -23,13 +23,20 @@ import { ViewChild, ViewEncapsulation, } from '@angular/core'; -import {animationFrameScheduler, asapScheduler, Observable, Subject, Observer} from 'rxjs'; +import { + animationFrameScheduler, + asapScheduler, + Observable, + Subject, + Observer, + Subscription, +} from 'rxjs'; import {auditTime, startWith, takeUntil} from 'rxjs/operators'; import {ScrollDispatcher} from './scroll-dispatcher'; import {CdkScrollable, ExtendedScrollToOptions} from './scrollable'; import {CdkVirtualForOf} from './virtual-for-of'; import {VIRTUAL_SCROLL_STRATEGY, VirtualScrollStrategy} from './virtual-scroll-strategy'; - +import {ViewportRuler} from './viewport-ruler'; /** Checks if the given ranges are equal. */ function rangesEqual(r1: ListRange, r2: ListRange): boolean { @@ -142,18 +149,33 @@ export class CdkVirtualScrollViewport extends CdkScrollable implements OnInit, O /** A list of functions to run after the next change detection cycle. */ private _runAfterChangeDetection: Function[] = []; + /** Subscription to changes in the viewport size. */ + private _viewportChanges = Subscription.EMPTY; + constructor(public elementRef: ElementRef, private _changeDetectorRef: ChangeDetectorRef, ngZone: NgZone, @Optional() @Inject(VIRTUAL_SCROLL_STRATEGY) private _scrollStrategy: VirtualScrollStrategy, @Optional() dir: Directionality, - scrollDispatcher: ScrollDispatcher) { + scrollDispatcher: ScrollDispatcher, + /** + * @deprecated `viewportRuler` parameter to become required. + * @breaking-change 11.0.0 + */ + @Optional() viewportRuler?: ViewportRuler) { super(elementRef, scrollDispatcher, ngZone, dir); if (!_scrollStrategy) { throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.'); } + + // @breaking-change 11.0.0 Remove null check for `viewportRuler`. + if (viewportRuler) { + this._viewportChanges = viewportRuler.change().subscribe(() => { + this.checkViewportSize(); + }); + } } ngOnInit() { @@ -188,6 +210,7 @@ export class CdkVirtualScrollViewport extends CdkScrollable implements OnInit, O // Complete all subjects this._renderedRangeSubject.complete(); this._detachedSubject.complete(); + this._viewportChanges.unsubscribe(); super.ngOnDestroy(); } diff --git a/tools/public_api_guard/cdk/scrolling.d.ts b/tools/public_api_guard/cdk/scrolling.d.ts index aeae3e41e7dc..26fb82fbafab 100644 --- a/tools/public_api_guard/cdk/scrolling.d.ts +++ b/tools/public_api_guard/cdk/scrolling.d.ts @@ -105,7 +105,8 @@ export declare class CdkVirtualScrollViewport extends CdkScrollable implements O orientation: 'horizontal' | 'vertical'; renderedRangeStream: Observable; scrolledIndexChange: Observable; - constructor(elementRef: ElementRef, _changeDetectorRef: ChangeDetectorRef, ngZone: NgZone, _scrollStrategy: VirtualScrollStrategy, dir: Directionality, scrollDispatcher: ScrollDispatcher); + constructor(elementRef: ElementRef, _changeDetectorRef: ChangeDetectorRef, ngZone: NgZone, _scrollStrategy: VirtualScrollStrategy, dir: Directionality, scrollDispatcher: ScrollDispatcher, + viewportRuler?: ViewportRuler); attach(forOf: CdkVirtualForOf): void; checkViewportSize(): void; detach(): void;