6
6
* found in the LICENSE file at https://angular.io/license
7
7
*/
8
8
9
- import { ArrayDataSource , CollectionViewer , DataSource , ListRange } from '@angular/cdk/collections' ;
9
+ import {
10
+ ArrayDataSource ,
11
+ CollectionViewer ,
12
+ DataSource ,
13
+ ListRange ,
14
+ DifferDataSource ,
15
+ } from '@angular/cdk/collections' ;
10
16
import {
11
17
Directive ,
12
18
DoCheck ,
@@ -75,18 +81,32 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
75
81
/** Subject that emits when a new DataSource instance is given. */
76
82
private _dataSourceChanges = new Subject < DataSource < T > > ( ) ;
77
83
84
+ /**
85
+ * Current differ data source. Needs to be kept in a separate
86
+ * property so we can run change detection on it.
87
+ */
88
+ private _differDataSource : DifferDataSource < T > | null = null ;
89
+
78
90
/** The DataSource to display. */
79
91
@Input ( )
80
92
get cdkVirtualForOf ( ) : DataSource < T > | Observable < T [ ] > | NgIterable < T > {
81
93
return this . _cdkVirtualForOf ;
82
94
}
83
95
set cdkVirtualForOf ( value : DataSource < T > | Observable < T [ ] > | NgIterable < T > ) {
84
96
this . _cdkVirtualForOf = value ;
85
- const ds = value instanceof DataSource ? value :
86
- // Slice the value if its an NgIterable to ensure we're working with an array.
87
- new ArrayDataSource < T > (
88
- value instanceof Observable ? value : Array . prototype . slice . call ( value || [ ] ) ) ;
89
- this . _dataSourceChanges . next ( ds ) ;
97
+
98
+ let dataSource : DataSource < T > ;
99
+
100
+ if ( value instanceof DataSource ) {
101
+ dataSource = value ;
102
+ } else if ( Array . isArray ( value ) ) {
103
+ this . _differDataSource = dataSource =
104
+ new DifferDataSource ( this . _differs , value , this . cdkVirtualForTrackBy ) ;
105
+ } else {
106
+ dataSource = new ArrayDataSource < T > ( value as T [ ] | Observable < T [ ] > ) ;
107
+ }
108
+
109
+ this . _dataSourceChanges . next ( dataSource ) ;
90
110
}
91
111
_cdkVirtualForOf : DataSource < T > | Observable < T [ ] > | NgIterable < T > ;
92
112
@@ -103,6 +123,10 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
103
123
this . _cdkVirtualForTrackBy = fn ?
104
124
( index , item ) => fn ( index + ( this . _renderedRange ? this . _renderedRange . start : 0 ) , item ) :
105
125
undefined ;
126
+
127
+ if ( this . _differDataSource ) {
128
+ this . _differDataSource . switchTrackBy ( this . _cdkVirtualForTrackBy ) ;
129
+ }
106
130
}
107
131
private _cdkVirtualForTrackBy : TrackByFunction < T > | undefined ;
108
132
@@ -215,6 +239,10 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
215
239
}
216
240
217
241
ngDoCheck ( ) {
242
+ if ( this . _differDataSource ) {
243
+ this . _differDataSource . doCheck ( ) ;
244
+ }
245
+
218
246
if ( this . _differ && this . _needsUpdate ) {
219
247
// TODO(mmalerba): We should differentiate needs update due to scrolling and a new portion of
220
248
// this list being rendered (can use simpler algorithm) vs needs update due to data actually
@@ -261,6 +289,10 @@ export class CdkVirtualForOf<T> implements CollectionViewer, DoCheck, OnDestroy
261
289
262
290
if ( oldDs ) {
263
291
oldDs . disconnect ( this ) ;
292
+
293
+ if ( oldDs === this . _differDataSource ) {
294
+ this . _differDataSource = null ;
295
+ }
264
296
}
265
297
266
298
this . _needsUpdate = true ;
0 commit comments