Skip to content

Commit 245bf36

Browse files
committed
change VirtualScrollStrategy interface a bit
1 parent 3393692 commit 245bf36

File tree

4 files changed

+97
-36
lines changed

4 files changed

+97
-36
lines changed

src/cdk/scrolling/virtual-for-of.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -252,16 +252,16 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
252252
/** Apply changes to the DOM. */
253253
private _applyChanges(changes: IterableChanges<T>) {
254254
// Detach all of the views and add them into an array to preserve their original order.
255-
const previousViews: EmbeddedViewRef<CdkVirtualForOfContext<T>>[] = [];
255+
const previousViews: (EmbeddedViewRef<CdkVirtualForOfContext<T>> | null)[] = [];
256256
for (let i = 0, len = this._viewContainerRef.length; i < len; i++) {
257257
previousViews.unshift(
258258
this._viewContainerRef.detach()! as EmbeddedViewRef<CdkVirtualForOfContext<T>>);
259259
}
260260

261261
// Mark the removed indices so we can recycle their views.
262262
changes.forEachRemovedItem(record => {
263-
this._templateCache.push(previousViews[record.previousIndex!]);
264-
delete previousViews[record.previousIndex!];
263+
this._templateCache.push(previousViews[record.previousIndex!]!);
264+
previousViews[record.previousIndex!] = null;
265265
});
266266

267267
// Queue up the newly added items to be inserted, recycling views from the cache if possible.
@@ -272,15 +272,15 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
272272

273273
// Queue up moved items to be re-inserted.
274274
changes.forEachMovedItem(record => {
275-
insertTuples[record.currentIndex!] = {record, view: previousViews[record.previousIndex!]};
276-
delete previousViews[record.previousIndex!];
275+
insertTuples[record.currentIndex!] = {record, view: previousViews[record.previousIndex!]!};
276+
previousViews[record.previousIndex!] = null;
277277
});
278278

279-
// We have deleted all of the views that were removed or moved from previousViews. What is left
280-
// is the unchanged items that we queue up to be re-inserted.
279+
// We have nulled-out all of the views that were removed or moved from previousViews. What is
280+
// left is the unchanged items that we queue up to be re-inserted.
281281
for (let i = 0, len = previousViews.length; i < len; i++) {
282282
if (previousViews[i]) {
283-
insertTuples[i] = {record: null, view: previousViews[i]};
283+
insertTuples[i] = {record: null, view: previousViews[i]!};
284284
}
285285
}
286286

src/cdk/scrolling/virtual-scroll-fixed-size.ts

Lines changed: 78 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,52 +6,112 @@ import {CdkVirtualScrollViewport} from './virtual-scroll-viewport';
66

77
/** Virtual scrolling strategy for lists with items of known fixed size. */
88
export class VirtualScrollFixedSizeStrategy implements VirtualScrollStrategy {
9-
private _viewport: CdkVirtualScrollViewport;
10-
11-
constructor(public itemSize: number, public bufferSize: number) {}
9+
/** The attached viewport. */
10+
private _viewport: CdkVirtualScrollViewport | null = null;
11+
12+
/** The size of the items in the virtually scrolling list. */
13+
private _itemSize: number;
14+
15+
/** The number of buffer items to render beyond the edge of the viewport. */
16+
private _bufferSize: number;
17+
18+
/**
19+
* @param itemSize The size of the items in the virtually scrolling list.
20+
* @param bufferSize he number of buffer items to render beyond the edge of the viewport.
21+
*/
22+
constructor(itemSize: number, bufferSize: number) {
23+
this._itemSize = itemSize;
24+
this._bufferSize = bufferSize;
25+
}
1226

13-
/** Initialize the strategy and specify the viewport it will be working with. */
14-
init(viewport: CdkVirtualScrollViewport) {
27+
/**
28+
* Attaches this scroll strategy to a viewport.
29+
* @param viewport The viewport to attach this strategy to.
30+
*/
31+
attach(viewport: CdkVirtualScrollViewport) {
1532
this._viewport = viewport;
16-
this._viewport.totalContentSize = this._viewport.dataLength * this.itemSize;
33+
this._updateTotalContentSize();
1734
this._updateRenderedRange();
1835
}
1936

20-
/** Re-initialize the strategy with the same viewport. */
21-
reinit() {
22-
if (this._viewport) {
23-
this.init(this._viewport);
24-
}
37+
/** Detaches this scroll strategy from the currently attached viewport. */
38+
detach() {
39+
this._viewport = null;
2540
}
2641

42+
/**
43+
* Update the item size and buffer size.
44+
* @param itemSize The size of the items in the virtually scrolling list.
45+
* @param bufferSize he number of buffer items to render beyond the edge of the viewport.
46+
*/
47+
updateItemAndBufferSize(itemSize: number, bufferSize: number) {
48+
this._itemSize = itemSize;
49+
this._bufferSize = bufferSize;
50+
this._updateTotalContentSize();
51+
this._updateRenderedRange();
52+
}
53+
54+
/** Called when the viewport is scrolled (debounced using requestAnimationFrame). */
2755
onContentScrolled() {
2856
this._updateRenderedRange();
2957
}
3058

59+
/** Called when the length of the data changes. */
3160
onDataLengthChanged() {
32-
this._viewport.totalContentSize = this._viewport.dataLength * this.itemSize;
61+
this._updateTotalContentSize();
3362
this._updateRenderedRange();
3463
}
3564

65+
/** Update the viewport's total content size. */
66+
private _updateTotalContentSize() {
67+
if (!this._viewport) {
68+
return;
69+
}
70+
71+
this._viewport.totalContentSize = this._viewport.dataLength * this._itemSize;
72+
};
73+
74+
/** Update the viewport's rendered range. */
3675
private _updateRenderedRange() {
76+
if (!this._viewport) {
77+
return;
78+
}
79+
3780
const scrollOffset = this._viewport.measureScrollOffset();
38-
const firstVisibleIndex = Math.floor(scrollOffset / this.itemSize);
81+
const firstVisibleIndex = Math.floor(scrollOffset / this._itemSize);
3982
const range = this._expandRange(
4083
{start: firstVisibleIndex, end: firstVisibleIndex},
41-
this.bufferSize,
42-
Math.ceil(this._viewport.viewportSize / this.itemSize) + this.bufferSize);
84+
this._bufferSize,
85+
Math.ceil(this._viewport.viewportSize / this._itemSize) + this._bufferSize);
4386
this._viewport.renderedRange = range;
44-
this._viewport.renderedContentOffset = this.itemSize * range.start;
87+
this._viewport.renderedContentOffset = this._itemSize * range.start;
4588
}
4689

90+
/**
91+
* Expand the given range by the given amount in either direction.
92+
* @param range The range to expand
93+
* @param expandStart The number of items to expand the start of the range by.
94+
* @param expandEnd The number of items to expand the end of the range by.
95+
* @return The expanded range.
96+
*/
4797
private _expandRange(range: Range, expandStart: number, expandEnd: number): Range {
98+
if (!this._viewport) {
99+
return {...range};
100+
}
101+
48102
const start = Math.max(0, range.start - expandStart);
49103
const end = Math.min(this._viewport.dataLength, range.end + expandEnd);
50104
return {start, end};
51105
}
52106
}
53107

54108

109+
/**
110+
* Provider factory for `VirtualScrollFixedSizeStrategy` that simply extracts the already created
111+
* `VirtualScrollFixedSizeStrategy` from the given directive.
112+
* @param fixedSizeDir The instance of `CdkVirtualScrollFixedSize` to extract the
113+
* `VirtualScrollFixedSizeStrategy` from.
114+
*/
55115
export function _virtualScrollFixedSizeStrategyFactory(fixedSizeDir: CdkVirtualScrollFixedSize) {
56116
return fixedSizeDir._scrollStrategy;
57117
}
@@ -73,11 +133,10 @@ export class CdkVirtualScrollFixedSize implements OnChanges {
73133
/** The number of extra elements to render on either side of the viewport. */
74134
@Input() bufferSize = 5;
75135

136+
/** The scroll strategy used by this directive. */
76137
_scrollStrategy = new VirtualScrollFixedSizeStrategy(this.itemSize, this.bufferSize);
77138

78139
ngOnChanges() {
79-
this._scrollStrategy.itemSize = this.itemSize;
80-
this._scrollStrategy.bufferSize = this.bufferSize;
81-
this._scrollStrategy.reinit();
140+
this._scrollStrategy.updateItemAndBufferSize(this.itemSize, this.bufferSize);
82141
}
83142
}

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

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,14 @@ export const VIRTUAL_SCROLL_STRATEGY =
99

1010
/** A strategy that dictates which items should be rendered in the viewport. */
1111
export interface VirtualScrollStrategy {
12-
/** Called after the viewport is initialized. */
13-
init(viewport: CdkVirtualScrollViewport): void;
12+
/**
13+
* Attaches this scroll strategy to a viewport.
14+
* @param viewport The viewport to attach this strategy to.
15+
*/
16+
attach(viewport: CdkVirtualScrollViewport): void;
17+
18+
/** Detaches this scroll strategy from the currently attached viewport. */
19+
detach(): void;
1420

1521
/** Called when the viewport is scrolled (debounced using requestAnimationFrame). */
1622
onContentScrolled();

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

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -108,8 +108,6 @@ export class CdkVirtualScrollViewport implements OnInit, DoCheck, OnDestroy {
108108

109109
private _scrollHandledStatus: 'needed' | 'pending' | 'done' = 'done';
110110

111-
private _scrollStrategyInited = false;
112-
113111
constructor(public elementRef: ElementRef, private _changeDetectorRef: ChangeDetectorRef,
114112
private _ngZone: NgZone,
115113
@Inject(VIRTUAL_SCROLL_STRATEGY) private _scrollStrategy: VirtualScrollStrategy) {}
@@ -125,9 +123,7 @@ export class CdkVirtualScrollViewport implements OnInit, DoCheck, OnDestroy {
125123
const len = data.length;
126124
if (len != this._dataLength) {
127125
this._dataLength = len;
128-
if (this._scrollStrategyInited) {
129-
this._scrollStrategy.onDataLengthChanged();
130-
}
126+
this._scrollStrategy.onDataLengthChanged();
131127
}
132128
});
133129
}
@@ -153,8 +149,7 @@ export class CdkVirtualScrollViewport implements OnInit, DoCheck, OnDestroy {
153149
this._markScrolled();
154150
});
155151
});
156-
this._scrollStrategy.init(this);
157-
this._scrollStrategyInited = true;
152+
this._scrollStrategy.attach(this);
158153
});
159154
}
160155

@@ -170,6 +165,7 @@ export class CdkVirtualScrollViewport implements OnInit, DoCheck, OnDestroy {
170165

171166
ngOnDestroy() {
172167
this.disconnect();
168+
this._scrollStrategy.detach();
173169

174170
// Complete all subjects
175171
this._disconnectSubject.complete();

0 commit comments

Comments
 (0)