@vaadin/grid 24.2.3 → 24.3.0-alpha10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (61) hide show
  1. package/package.json +18 -13
  2. package/src/vaadin-grid-a11y-mixin.js +1 -1
  3. package/src/vaadin-grid-active-item-mixin.js +1 -0
  4. package/src/vaadin-grid-array-data-provider-mixin.js +14 -17
  5. package/src/vaadin-grid-column-group-mixin.d.ts +20 -0
  6. package/src/vaadin-grid-column-group-mixin.js +364 -0
  7. package/src/vaadin-grid-column-group.d.ts +4 -14
  8. package/src/vaadin-grid-column-group.js +5 -355
  9. package/src/vaadin-grid-column-mixin.d.ts +170 -0
  10. package/src/vaadin-grid-column-mixin.js +958 -0
  11. package/src/vaadin-grid-column.d.ts +11 -138
  12. package/src/vaadin-grid-column.js +5 -876
  13. package/src/vaadin-grid-data-provider-mixin.d.ts +6 -30
  14. package/src/vaadin-grid-data-provider-mixin.js +122 -246
  15. package/src/vaadin-grid-drag-and-drop-mixin.js +17 -5
  16. package/src/vaadin-grid-dynamic-columns-mixin.js +22 -17
  17. package/src/vaadin-grid-filter-column-mixin.d.ts +22 -0
  18. package/src/vaadin-grid-filter-column-mixin.js +106 -0
  19. package/src/vaadin-grid-filter-column.d.ts +9 -11
  20. package/src/vaadin-grid-filter-column.js +3 -90
  21. package/src/vaadin-grid-filter-element-mixin.d.ts +34 -0
  22. package/src/vaadin-grid-filter-element-mixin.js +108 -0
  23. package/src/vaadin-grid-filter-mixin.js +4 -4
  24. package/src/vaadin-grid-filter.d.ts +4 -21
  25. package/src/vaadin-grid-filter.js +5 -84
  26. package/src/vaadin-grid-helpers.js +94 -0
  27. package/src/vaadin-grid-keyboard-navigation-mixin.js +11 -4
  28. package/src/vaadin-grid-mixin.js +21 -37
  29. package/src/vaadin-grid-row-details-mixin.js +7 -8
  30. package/src/vaadin-grid-scroll-mixin.js +2 -1
  31. package/src/vaadin-grid-selection-column-base-mixin.js +12 -4
  32. package/src/vaadin-grid-selection-column-mixin.d.ts +24 -0
  33. package/src/vaadin-grid-selection-column-mixin.js +194 -0
  34. package/src/vaadin-grid-selection-column.d.ts +13 -17
  35. package/src/vaadin-grid-selection-column.js +4 -186
  36. package/src/vaadin-grid-selection-mixin.js +4 -3
  37. package/src/vaadin-grid-sort-column-mixin.d.ts +36 -0
  38. package/src/vaadin-grid-sort-column-mixin.js +101 -0
  39. package/src/vaadin-grid-sort-column.d.ts +8 -26
  40. package/src/vaadin-grid-sort-column.js +3 -87
  41. package/src/vaadin-grid-sorter-mixin.d.ts +44 -0
  42. package/src/vaadin-grid-sorter-mixin.js +200 -0
  43. package/src/vaadin-grid-sorter.d.ts +3 -32
  44. package/src/vaadin-grid-sorter.js +5 -181
  45. package/src/vaadin-grid-styles.js +341 -345
  46. package/src/vaadin-grid-styling-mixin.js +8 -2
  47. package/src/vaadin-grid-tree-column-mixin.d.ts +18 -0
  48. package/src/vaadin-grid-tree-column-mixin.js +99 -0
  49. package/src/vaadin-grid-tree-column.d.ts +9 -7
  50. package/src/vaadin-grid-tree-column.js +3 -82
  51. package/src/vaadin-grid-tree-toggle-mixin.d.ts +39 -0
  52. package/src/vaadin-grid-tree-toggle-mixin.js +153 -0
  53. package/src/vaadin-grid-tree-toggle.d.ts +4 -27
  54. package/src/vaadin-grid-tree-toggle.js +9 -141
  55. package/src/vaadin-grid.d.ts +3 -0
  56. package/src/vaadin-grid.js +7 -2
  57. package/theme/lumo/vaadin-grid-sorter-styles.js +1 -1
  58. package/theme/lumo/vaadin-grid-styles.js +15 -14
  59. package/theme/material/vaadin-grid-styles.js +15 -10
  60. package/web-types.json +331 -126
  61. package/web-types.lit.json +114 -58
@@ -4,6 +4,10 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import type { Constructor } from '@open-wc/dedupe-mixin';
7
+ import type {
8
+ DataProvider,
9
+ DataProviderCallback,
10
+ } from '@vaadin/component-base/src/data-provider-controller/data-provider-controller.js';
7
11
  import { GridSorterDirection } from './vaadin-grid-sorter.js';
8
12
 
9
13
  export { GridSorterDirection };
@@ -18,7 +22,7 @@ export interface GridSorterDefinition {
18
22
  direction: GridSorterDirection;
19
23
  }
20
24
 
21
- export type GridDataProviderCallback<TItem> = (items: TItem[], size?: number) => void;
25
+ export type GridDataProviderCallback<TItem> = DataProviderCallback<TItem>;
22
26
 
23
27
  export type GridDataProviderParams<TItem> = {
24
28
  page: number;
@@ -28,35 +32,7 @@ export type GridDataProviderParams<TItem> = {
28
32
  parentItem?: TItem;
29
33
  };
30
34
 
31
- export type GridDataProvider<TItem> = (
32
- params: GridDataProviderParams<TItem>,
33
- callback: GridDataProviderCallback<TItem>,
34
- ) => void;
35
-
36
- export declare class ItemCache<TItem> {
37
- grid: HTMLElement;
38
- parentCache: ItemCache<TItem> | undefined;
39
- parentItem: TItem | undefined;
40
- itemCaches: object | null;
41
- items: object | null;
42
- effectiveSize: number;
43
- size: number;
44
- pendingRequests: object | null;
45
-
46
- constructor(grid: HTMLElement, parentCache: ItemCache<TItem> | undefined, parentItem: TItem | undefined);
47
-
48
- isLoading(): boolean;
49
-
50
- getItemForIndex(index: number): TItem | undefined;
51
-
52
- updateSize(): void;
53
-
54
- ensureSubCacheForScaledIndex(scaledIndex: number): void;
55
-
56
- getCacheAndIndex(index: number): { cache: ItemCache<TItem>; scaledIndex: number };
57
-
58
- getFlatIndex(scaledIndex: number): number;
59
- }
35
+ export type GridDataProvider<TItem> = DataProvider<TItem, GridDataProviderParams<TItem>>;
60
36
 
61
37
  export declare function DataProviderMixin<TItem, T extends Constructor<HTMLElement>>(
62
38
  base: T,
@@ -4,116 +4,11 @@
4
4
  * This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
5
5
  */
6
6
  import { timeOut } from '@vaadin/component-base/src/async.js';
7
+ import { DataProviderController } from '@vaadin/component-base/src/data-provider-controller/data-provider-controller.js';
7
8
  import { Debouncer } from '@vaadin/component-base/src/debounce.js';
8
9
  import { get } from '@vaadin/component-base/src/path-utils.js';
9
10
  import { getBodyRowCells, updateCellsPart, updateState } from './vaadin-grid-helpers.js';
10
11
 
11
- /**
12
- * @private
13
- */
14
- export const ItemCache = class ItemCache {
15
- /**
16
- * @param {!HTMLElement} grid
17
- * @param {!ItemCache | undefined} parentCache
18
- * @param {!GridItem | undefined} parentItem
19
- */
20
- constructor(grid, parentCache, parentItem) {
21
- /** @type {!HTMLElement} */
22
- this.grid = grid;
23
- /** @type {!ItemCache | undefined} */
24
- this.parentCache = parentCache;
25
- /** @type {!GridItem | undefined} */
26
- this.parentItem = parentItem;
27
- /** @type {object} */
28
- this.itemCaches = {};
29
- /** @type {object[]} */
30
- this.items = [];
31
- /** @type {number} */
32
- this.effectiveSize = 0;
33
- /** @type {number} */
34
- this.size = 0;
35
- /** @type {object} */
36
- this.pendingRequests = {};
37
- }
38
-
39
- /**
40
- * @return {boolean}
41
- */
42
- isLoading() {
43
- return Boolean(
44
- Object.keys(this.pendingRequests).length ||
45
- Object.keys(this.itemCaches).filter((index) => {
46
- return this.itemCaches[index].isLoading();
47
- })[0],
48
- );
49
- }
50
-
51
- /**
52
- * @param {number} index
53
- * @return {!GridItem | undefined}
54
- */
55
- getItemForIndex(index) {
56
- const { cache, scaledIndex } = this.getCacheAndIndex(index);
57
- return cache.items[scaledIndex];
58
- }
59
-
60
- updateSize() {
61
- this.effectiveSize =
62
- !this.parentItem || this.grid._isExpanded(this.parentItem)
63
- ? this.size +
64
- Object.keys(this.itemCaches).reduce((prev, curr) => {
65
- const subCache = this.itemCaches[curr];
66
- subCache.updateSize();
67
- return prev + subCache.effectiveSize;
68
- }, 0)
69
- : 0;
70
- }
71
-
72
- /**
73
- * @param {number} scaledIndex
74
- */
75
- ensureSubCacheForScaledIndex(scaledIndex) {
76
- if (!this.itemCaches[scaledIndex]) {
77
- const subCache = new ItemCache(this.grid, this, this.items[scaledIndex]);
78
- this.itemCaches[scaledIndex] = subCache;
79
- this.grid._loadPage(0, subCache);
80
- }
81
- }
82
-
83
- /**
84
- * @param {number} index
85
- * @return {{cache: !ItemCache, scaledIndex: number}}
86
- */
87
- getCacheAndIndex(index) {
88
- let thisLevelIndex = index;
89
- for (const [index, subCache] of Object.entries(this.itemCaches)) {
90
- const numberIndex = Number(index);
91
- if (thisLevelIndex <= numberIndex) {
92
- return { cache: this, scaledIndex: thisLevelIndex };
93
- } else if (thisLevelIndex <= numberIndex + subCache.effectiveSize) {
94
- return subCache.getCacheAndIndex(thisLevelIndex - numberIndex - 1);
95
- }
96
- thisLevelIndex -= subCache.effectiveSize;
97
- }
98
- return { cache: this, scaledIndex: thisLevelIndex };
99
- }
100
-
101
- /**
102
- * Gets the scaled index as flattened index on this cache level.
103
- * In practice, this means that the effective size of any expanded
104
- * subcaches preceding the index are added to the value.
105
- * @param {number} scaledIndex
106
- * @return {number} The flat index on this cache level.
107
- */
108
- getFlatIndex(scaledIndex) {
109
- const clampedIndex = Math.max(0, Math.min(this.size - 1, scaledIndex));
110
-
111
- return Object.entries(this.itemCaches).reduce((prev, [index, subCache]) => {
112
- return clampedIndex > Number(index) ? prev + subCache.effectiveSize : prev;
113
- }, clampedIndex);
114
- }
115
- };
116
-
117
12
  /**
118
13
  * @polymerMixin
119
14
  */
@@ -129,6 +24,16 @@ export const DataProviderMixin = (superClass) =>
129
24
  size: {
130
25
  type: Number,
131
26
  notify: true,
27
+ sync: true,
28
+ },
29
+
30
+ /**
31
+ * @type {number}
32
+ * @protected
33
+ */
34
+ _flatSize: {
35
+ type: Number,
36
+ sync: true,
132
37
  },
133
38
 
134
39
  /**
@@ -140,6 +45,7 @@ export const DataProviderMixin = (superClass) =>
140
45
  type: Number,
141
46
  value: 50,
142
47
  observer: '_pageSizeChanged',
48
+ sync: true,
143
49
  },
144
50
 
145
51
  /**
@@ -169,6 +75,7 @@ export const DataProviderMixin = (superClass) =>
169
75
  type: Object,
170
76
  notify: true,
171
77
  observer: '_dataProviderChanged',
78
+ sync: true,
172
79
  },
173
80
 
174
81
  /**
@@ -181,24 +88,13 @@ export const DataProviderMixin = (superClass) =>
181
88
  reflectToAttribute: true,
182
89
  },
183
90
 
184
- /**
185
- * @type {!ItemCache}
186
- * @protected
187
- */
188
- _cache: {
189
- type: Object,
190
- value() {
191
- const cache = new ItemCache(this);
192
- return cache;
193
- },
194
- },
195
-
196
91
  /**
197
92
  * @protected
198
93
  */
199
94
  _hasData: {
200
95
  type: Boolean,
201
96
  value: false,
97
+ sync: true,
202
98
  },
203
99
 
204
100
  /**
@@ -209,6 +105,7 @@ export const DataProviderMixin = (superClass) =>
209
105
  type: String,
210
106
  value: 'children',
211
107
  observer: '__itemHasChildrenPathChanged',
108
+ sync: true,
212
109
  },
213
110
 
214
111
  /**
@@ -218,6 +115,7 @@ export const DataProviderMixin = (superClass) =>
218
115
  itemIdPath: {
219
116
  type: String,
220
117
  value: null,
118
+ sync: true,
221
119
  },
222
120
 
223
121
  /**
@@ -228,6 +126,7 @@ export const DataProviderMixin = (superClass) =>
228
126
  type: Object,
229
127
  notify: true,
230
128
  value: () => [],
129
+ sync: true,
231
130
  },
232
131
 
233
132
  /**
@@ -235,21 +134,60 @@ export const DataProviderMixin = (superClass) =>
235
134
  */
236
135
  __expandedKeys: {
237
136
  type: Object,
238
- computed: '__computeExpandedKeys(itemIdPath, expandedItems.*)',
137
+ computed: '__computeExpandedKeys(itemIdPath, expandedItems)',
239
138
  },
240
139
  };
241
140
  }
242
141
 
243
142
  static get observers() {
244
- return ['_sizeChanged(size)', '_expandedItemsChanged(expandedItems.*)'];
143
+ return ['_sizeChanged(size)', '_expandedItemsChanged(expandedItems)'];
144
+ }
145
+
146
+ constructor() {
147
+ super();
148
+
149
+ /** @type {DataProviderController} */
150
+ this._dataProviderController = new DataProviderController(this, {
151
+ size: this.size,
152
+ pageSize: this.pageSize,
153
+ getItemId: this.getItemId.bind(this),
154
+ isExpanded: this._isExpanded.bind(this),
155
+ dataProvider: this.dataProvider ? this.dataProvider.bind(this) : null,
156
+ dataProviderParams: () => {
157
+ return {
158
+ sortOrders: this._mapSorters(),
159
+ filters: this._mapFilters(),
160
+ };
161
+ },
162
+ });
163
+
164
+ this._dataProviderController.addEventListener('page-requested', this._onDataProviderPageRequested.bind(this));
165
+ this._dataProviderController.addEventListener('page-received', this._onDataProviderPageReceived.bind(this));
166
+ this._dataProviderController.addEventListener('page-loaded', this._onDataProviderPageLoaded.bind(this));
167
+ }
168
+
169
+ /**
170
+ * @protected
171
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
172
+ */
173
+ get _cache() {
174
+ console.warn('<vaadin-grid> The `_cache` property is deprecated and will be removed in Vaadin 25.');
175
+ return this._dataProviderController.rootCache;
176
+ }
177
+
178
+ /**
179
+ * @protected
180
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
181
+ */
182
+ get _effectiveSize() {
183
+ console.warn('<vaadin-grid> The `_effectiveSize` property is deprecated and will be removed in Vaadin 25.');
184
+ return this._flatSize;
245
185
  }
246
186
 
247
187
  /** @private */
248
188
  _sizeChanged(size) {
249
- const delta = size - this._cache.size;
250
- this._cache.size += delta;
251
- this._cache.effectiveSize += delta;
252
- this._effectiveSize = this._cache.effectiveSize;
189
+ this._dataProviderController.setSize(size);
190
+ this._flatSize = this._dataProviderController.flatSize;
253
191
  }
254
192
 
255
193
  /** @private */
@@ -267,22 +205,22 @@ export const DataProviderMixin = (superClass) =>
267
205
  * @protected
268
206
  */
269
207
  _getItem(index, el) {
270
- if (index >= this._effectiveSize) {
208
+ if (index >= this._flatSize) {
271
209
  return;
272
210
  }
273
211
 
274
212
  el.index = index;
275
- const { cache, scaledIndex } = this._cache.getCacheAndIndex(index);
276
- const item = cache.items[scaledIndex];
213
+
214
+ const { item } = this._dataProviderController.getFlatIndexContext(index);
277
215
  if (item) {
278
216
  this.__updateLoading(el, false);
279
217
  this._updateItem(el, item);
280
218
  if (this._isExpanded(item)) {
281
- cache.ensureSubCacheForScaledIndex(scaledIndex);
219
+ this._dataProviderController.ensureFlatIndexHierarchy(index);
282
220
  }
283
221
  } else {
284
222
  this.__updateLoading(el, true);
285
- this._loadPage(this._getPageForIndex(scaledIndex), cache);
223
+ this._dataProviderController.ensureFlatIndexLoaded(index);
286
224
  }
287
225
  }
288
226
 
@@ -317,19 +255,19 @@ export const DataProviderMixin = (superClass) =>
317
255
  * @protected
318
256
  */
319
257
  _isExpanded(item) {
320
- return this.__expandedKeys.has(this.getItemId(item));
258
+ return this.__expandedKeys && this.__expandedKeys.has(this.getItemId(item));
321
259
  }
322
260
 
323
261
  /** @private */
324
262
  _expandedItemsChanged() {
325
- this._cache.updateSize();
326
- this._effectiveSize = this._cache.effectiveSize;
263
+ this._dataProviderController.recalculateFlatSize();
264
+ this._flatSize = this._dataProviderController.flatSize;
327
265
  this.__updateVisibleRows();
328
266
  }
329
267
 
330
268
  /** @private */
331
269
  __computeExpandedKeys(itemIdPath, expandedItems) {
332
- const expanded = expandedItems.base || [];
270
+ const expanded = expandedItems || [];
333
271
  const expandedKeys = new Set();
334
272
  expanded.forEach((item) => {
335
273
  expandedKeys.add(this.getItemId(item));
@@ -363,13 +301,8 @@ export const DataProviderMixin = (superClass) =>
363
301
  * @return {number}
364
302
  * @protected
365
303
  */
366
- _getIndexLevel(index) {
367
- let { cache } = this._cache.getCacheAndIndex(index);
368
- let level = 0;
369
- while (cache.parentCache) {
370
- cache = cache.parentCache;
371
- level += 1;
372
- }
304
+ _getIndexLevel(index = 0) {
305
+ const { level } = this._dataProviderController.getFlatIndexContext(index);
373
306
  return level;
374
307
  }
375
308
 
@@ -377,106 +310,71 @@ export const DataProviderMixin = (superClass) =>
377
310
  * @param {number} page
378
311
  * @param {ItemCache} cache
379
312
  * @protected
313
+ * @deprecated since 24.3 and will be removed in Vaadin 25.
380
314
  */
381
315
  _loadPage(page, cache) {
382
- // Make sure same page isn't requested multiple times.
383
- if (!cache.pendingRequests[page] && this.dataProvider) {
384
- this._setLoading(true);
385
- cache.pendingRequests[page] = true;
386
- const params = {
387
- page,
388
- pageSize: this.pageSize,
389
- sortOrders: this._mapSorters(),
390
- filters: this._mapFilters(),
391
- parentItem: cache.parentItem,
392
- };
393
-
394
- this.dataProvider(params, (items, size) => {
395
- if (size !== undefined) {
396
- cache.size = size;
397
- } else if (params.parentItem) {
398
- cache.size = items.length;
399
- }
316
+ console.warn('<vaadin-grid> The `_loadPage` method is deprecated and will be removed in Vaadin 25.');
317
+ this._dataProviderController.__loadCachePage(cache, page);
318
+ }
400
319
 
401
- // Populate the cache with new items
402
- items.forEach((item, itemsIndex) => {
403
- const itemIndex = page * this.pageSize + itemsIndex;
404
- cache.items[itemIndex] = item;
405
- });
406
-
407
- // With the new items added, update the cache size and the grid's effective size
408
- this._cache.updateSize();
409
- this._effectiveSize = this._cache.effectiveSize;
410
-
411
- // After updating the cache, check if some of the expanded items should have sub-caches loaded
412
- this._getRenderedRows().forEach((row) => {
413
- const { cache, scaledIndex } = this._cache.getCacheAndIndex(row.index);
414
- const item = cache.items[scaledIndex];
415
- if (item && this._isExpanded(item)) {
416
- cache.ensureSubCacheForScaledIndex(scaledIndex);
417
- }
418
- });
419
-
420
- this._hasData = true;
421
-
422
- // Remove the pending request
423
- delete cache.pendingRequests[page];
424
-
425
- // Schedule a debouncer to update the visible rows
426
- this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
427
- this._setLoading(false);
428
-
429
- this._getRenderedRows().forEach((row) => {
430
- const cachedItem = this._cache.getItemForIndex(row.index);
431
- if (cachedItem) {
432
- this._getItem(row.index, row);
433
- }
434
- });
435
-
436
- this.__scrollToPendingIndexes();
437
- this.__dispatchPendingBodyCellFocus();
438
- });
439
-
440
- // If the grid is not loading anything, flush the debouncer immediately
441
- if (!this._cache.isLoading()) {
442
- this._debouncerApplyCachedData.flush();
443
- }
320
+ /** @protected */
321
+ _onDataProviderPageRequested() {
322
+ this._setLoading(true);
323
+ }
444
324
 
445
- // Notify that new data has been received
446
- this._onDataProviderPageLoaded();
447
- });
448
- }
325
+ /** @protected */
326
+ _onDataProviderPageReceived() {
327
+ // With the new items added, update the cache size and the grid's effective size
328
+ this._flatSize = this._dataProviderController.flatSize;
329
+
330
+ // After updating the cache, check if some of the expanded items should have sub-caches loaded
331
+ this._getRenderedRows().forEach((row) => {
332
+ this._dataProviderController.ensureFlatIndexHierarchy(row.index);
333
+ });
334
+
335
+ this._hasData = true;
449
336
  }
450
337
 
451
338
  /** @protected */
452
- _onDataProviderPageLoaded() {}
339
+ _onDataProviderPageLoaded() {
340
+ // Schedule a debouncer to update the visible rows
341
+ this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
342
+ this._setLoading(false);
343
+
344
+ this._getRenderedRows().forEach((row) => {
345
+ const { item } = this._dataProviderController.getFlatIndexContext(row.index);
346
+ if (item) {
347
+ this._getItem(row.index, row);
348
+ }
349
+ });
453
350
 
454
- /**
455
- * @param {number} index
456
- * @return {number}
457
- * @private
458
- */
459
- _getPageForIndex(index) {
460
- return Math.floor(index / this.pageSize);
351
+ this.__scrollToPendingIndexes();
352
+ this.__dispatchPendingBodyCellFocus();
353
+ });
354
+
355
+ // If the grid is not loading anything, flush the debouncer immediately
356
+ if (!this._dataProviderController.isLoading()) {
357
+ this._debouncerApplyCachedData.flush();
358
+ }
461
359
  }
462
360
 
463
361
  /**
464
362
  * Clears the cached pages and reloads data from dataprovider when needed.
465
363
  */
466
364
  clearCache() {
467
- this._cache = new ItemCache(this);
468
- this._cache.size = this.size || 0;
469
- this._cache.updateSize();
365
+ this._dataProviderController.clearCache();
470
366
  this._hasData = false;
471
367
  this.__updateVisibleRows();
472
368
 
473
- if (!this._effectiveSize) {
474
- this._loadPage(0, this._cache);
369
+ if (!this._flatSize) {
370
+ this._dataProviderController.loadFirstPage();
475
371
  }
476
372
  }
477
373
 
478
374
  /** @private */
479
375
  _pageSizeChanged(pageSize, oldPageSize) {
376
+ this._dataProviderController.setPageSize(pageSize);
377
+
480
378
  if (oldPageSize !== undefined && pageSize !== oldPageSize) {
481
379
  this.clearCache();
482
380
  }
@@ -484,7 +382,7 @@ export const DataProviderMixin = (superClass) =>
484
382
 
485
383
  /** @protected */
486
384
  _checkSize() {
487
- if (this.size === undefined && this._effectiveSize === 0) {
385
+ if (this.size === undefined && this._flatSize === 0) {
488
386
  console.warn(
489
387
  'The <vaadin-grid> needs the total number of items in' +
490
388
  ' order to display rows, which you can specify either by setting' +
@@ -496,6 +394,8 @@ export const DataProviderMixin = (superClass) =>
496
394
 
497
395
  /** @private */
498
396
  _dataProviderChanged(dataProvider, oldDataProvider) {
397
+ this._dataProviderController.setDataProvider(dataProvider ? dataProvider.bind(this) : null);
398
+
499
399
  if (oldDataProvider !== undefined) {
500
400
  this.clearCache();
501
401
  }
@@ -514,7 +414,7 @@ export const DataProviderMixin = (superClass) =>
514
414
  if (!this._hasData) {
515
415
  // Load data before adding rows to make sure they have content when
516
416
  // rendered for the first time.
517
- this._loadPage(0, this._cache);
417
+ this._dataProviderController.loadFirstPage();
518
418
  }
519
419
  }
520
420
 
@@ -564,39 +464,15 @@ export const DataProviderMixin = (superClass) =>
564
464
  // ending up in a loading state. Try scrolling to the index until the target
565
465
  // index stabilizes.
566
466
  let targetIndex;
567
- while (targetIndex !== (targetIndex = this.__getGlobalFlatIndex(indexes))) {
467
+ while (targetIndex !== (targetIndex = this._dataProviderController.getFlatIndexByPath(indexes))) {
568
468
  this._scrollToFlatIndex(targetIndex);
569
469
  }
570
470
 
571
- if (this._cache.isLoading() || !this.clientHeight) {
471
+ if (this._dataProviderController.isLoading() || !this.clientHeight) {
572
472
  this.__pendingScrollToIndexes = indexes;
573
473
  }
574
474
  }
575
475
 
576
- /**
577
- * Recursively returns the globally flat index of the item the given indexes point to.
578
- * Each index in the array points to a sub-item of the previous index.
579
- * Using `Infinity` as an index will point to the last item on the level.
580
- *
581
- * @param {!Array<number>} indexes
582
- * @param {!ItemCache} cache
583
- * @param {number} flatIndex
584
- * @return {number}
585
- * @private
586
- */
587
- __getGlobalFlatIndex([levelIndex, ...subIndexes], cache = this._cache, flatIndex = 0) {
588
- if (levelIndex === Infinity) {
589
- // Treat Infinity as the last index on the level
590
- levelIndex = cache.size - 1;
591
- }
592
- const flatIndexOnLevel = cache.getFlatIndex(levelIndex);
593
- const subCache = cache.itemCaches[levelIndex];
594
- if (subCache && subCache.effectiveSize && subIndexes.length) {
595
- return this.__getGlobalFlatIndex(subIndexes, subCache, flatIndex + flatIndexOnLevel + 1);
596
- }
597
- return flatIndex + flatIndexOnLevel;
598
- }
599
-
600
476
  /** @private */
601
477
  __scrollToPendingIndexes() {
602
478
  if (this.__pendingScrollToIndexes && this.$.items.children.length) {
@@ -45,13 +45,19 @@ export const DragAndDropMixin = (superClass) =>
45
45
  * @attr {between|on-top|on-top-or-between|on-grid} drop-mode
46
46
  * @type {GridDropMode | null | undefined}
47
47
  */
48
- dropMode: String,
48
+ dropMode: {
49
+ type: String,
50
+ sync: true,
51
+ },
49
52
 
50
53
  /**
51
54
  * Marks the grid's rows to be available for dragging.
52
55
  * @attr {boolean} rows-draggable
53
56
  */
54
- rowsDraggable: Boolean,
57
+ rowsDraggable: {
58
+ type: Boolean,
59
+ sync: true,
60
+ },
55
61
 
56
62
  /**
57
63
  * A function that filters dragging of specific grid rows. The return value should be false
@@ -68,7 +74,10 @@ export const DragAndDropMixin = (superClass) =>
68
74
  *
69
75
  * @type {GridDragAndDropFilter | null | undefined}
70
76
  */
71
- dragFilter: Function,
77
+ dragFilter: {
78
+ type: Function,
79
+ sync: true,
80
+ },
72
81
 
73
82
  /**
74
83
  * A function that filters dropping on specific grid rows. The return value should be false
@@ -85,7 +94,10 @@ export const DragAndDropMixin = (superClass) =>
85
94
  *
86
95
  * @type {GridDragAndDropFilter | null | undefined}
87
96
  */
88
- dropFilter: Function,
97
+ dropFilter: {
98
+ type: Function,
99
+ sync: true,
100
+ },
89
101
 
90
102
  /** @private */
91
103
  __dndAutoScrollThreshold: {
@@ -211,7 +223,7 @@ export const DragAndDropMixin = (superClass) =>
211
223
 
212
224
  let row = e.composedPath().find((node) => node.localName === 'tr');
213
225
 
214
- if (!this._effectiveSize || this.dropMode === DropMode.ON_GRID) {
226
+ if (!this._flatSize || this.dropMode === DropMode.ON_GRID) {
215
227
  // The grid is empty or "on-grid" drop mode was used, always default to "empty"
216
228
  this._dropLocation = DropLocation.EMPTY;
217
229
  } else if (!row || row.parentNode !== this.$.items) {