Skip to content

Commit 78e7207

Browse files
crisbetojosephperrott
authored andcommitted
fix(scrolling): virtual scroll viewport error during server-side rendering (#15299)
Fixes the virtual scroll viewport throwing an error during server-side rendering, because it relies on a scheduler that uses `requestAnimationFrame`. Fixes #15291.
1 parent cb057d2 commit 78e7207

File tree

3 files changed

+23
-3
lines changed

3 files changed

+23
-3
lines changed

src/cdk/scrolling/virtual-scroll-viewport.ts

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ import {
2323
ViewChild,
2424
ViewEncapsulation,
2525
} from '@angular/core';
26-
import {animationFrameScheduler, Observable, Subject, Observer} from 'rxjs';
26+
import {animationFrameScheduler, asapScheduler, Observable, Subject, Observer} from 'rxjs';
2727
import {auditTime, startWith, takeUntil} from 'rxjs/operators';
2828
import {ScrollDispatcher} from './scroll-dispatcher';
2929
import {CdkScrollable, ExtendedScrollToOptions} from './scrollable';
@@ -36,6 +36,14 @@ function rangesEqual(r1: ListRange, r2: ListRange): boolean {
3636
return r1.start == r2.start && r1.end == r2.end;
3737
}
3838

39+
/**
40+
* Scheduler to be used for scroll events. Needs to fall back to
41+
* something that doesn't rely on requestAnimationFrame on environments
42+
* that don't support it (e.g. server-side rendering).
43+
*/
44+
const SCROLL_SCHEDULER =
45+
typeof requestAnimationFrame !== 'undefined' ? animationFrameScheduler : asapScheduler;
46+
3947

4048
/** A viewport that virtualizes it's scrolling with the help of `CdkVirtualForOf`. */
4149
@Component({
@@ -157,7 +165,7 @@ export class CdkVirtualScrollViewport extends CdkScrollable implements OnInit, O
157165
// Collect multiple events into one until the next animation frame. This way if
158166
// there are multiple scroll events in the same frame we only need to recheck
159167
// our layout once.
160-
auditTime(0, animationFrameScheduler))
168+
auditTime(0, SCROLL_SCHEDULER))
161169
.subscribe(() => this._scrollStrategy.onContentScrolled());
162170

163171
this._markChangeDetectionNeeded();

src/universal-app/kitchen-sink/kitchen-sink.html

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,3 +372,11 @@ <h2>Drag and Drop</h2>
372372
<li cdkDrag>One</li>
373373
<li cdkDrag>Two</li>
374374
</ul>
375+
376+
<h2>Virtual scroll</h2>
377+
378+
<cdk-virtual-scroll-viewport itemSize="50">
379+
<div *cdkVirtualFor="let size of virtualScrollData; let i = index" style="height: 50px">
380+
Item #{{i}}
381+
</div>
382+
</cdk-virtual-scroll-viewport>

src/universal-app/kitchen-sink/kitchen-sink.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import {ViewportRuler} from '@angular/cdk/scrolling';
1+
import {ViewportRuler, ScrollingModule} from '@angular/cdk/scrolling';
22
import {
33
CdkTableModule,
44
DataSource
@@ -77,6 +77,9 @@ export class KitchenSink {
7777
/** Data source for the CDK and Material table. */
7878
tableDataSource = new TableDataSource();
7979

80+
/** Data used to render a virtual scrolling list. */
81+
virtualScrollData = Array(10000).fill(50);
82+
8083
constructor(
8184
snackBar: MatSnackBar,
8285
dialog: MatDialog,
@@ -135,6 +138,7 @@ export class KitchenSink {
135138
MatSortModule,
136139
MatTableModule,
137140
MatStepperModule,
141+
ScrollingModule,
138142

139143
// CDK Modules
140144
CdkTableModule,

0 commit comments

Comments
 (0)