@vaadin/grid 24.2.0-beta2 → 24.2.0-beta3
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.
- package/package.json +10 -10
- package/src/vaadin-grid-array-data-provider-mixin.js +1 -1
- package/src/vaadin-grid-column-group-mixin.d.ts +20 -0
- package/src/vaadin-grid-column-group-mixin.js +369 -0
- package/src/vaadin-grid-column-group.d.ts +4 -14
- package/src/vaadin-grid-column-group.js +5 -355
- package/src/vaadin-grid-column-mixin.d.ts +156 -0
- package/src/vaadin-grid-column-mixin.js +887 -0
- package/src/vaadin-grid-column.d.ts +11 -138
- package/src/vaadin-grid-column.js +3 -876
- package/src/vaadin-grid-data-provider-mixin.d.ts +6 -30
- package/src/vaadin-grid-data-provider-mixin.js +100 -241
- package/src/vaadin-grid-drag-and-drop-mixin.js +1 -1
- package/src/vaadin-grid-filter-element-mixin.d.ts +34 -0
- package/src/vaadin-grid-filter-element-mixin.js +99 -0
- package/src/vaadin-grid-filter.d.ts +4 -21
- package/src/vaadin-grid-filter.js +5 -84
- package/src/vaadin-grid-keyboard-navigation-mixin.js +2 -2
- package/src/vaadin-grid-mixin.js +10 -10
- package/src/vaadin-grid-scroll-mixin.js +1 -1
- package/src/vaadin-grid-sorter-mixin.d.ts +44 -0
- package/src/vaadin-grid-sorter-mixin.js +198 -0
- package/src/vaadin-grid-sorter.d.ts +3 -32
- package/src/vaadin-grid-sorter.js +5 -181
- package/src/vaadin-grid-tree-column-mixin.d.ts +19 -0
- package/src/vaadin-grid-tree-column-mixin.js +92 -0
- package/src/vaadin-grid-tree-column.d.ts +9 -7
- package/src/vaadin-grid-tree-column.js +3 -82
- package/src/vaadin-grid-tree-toggle-mixin.d.ts +39 -0
- package/src/vaadin-grid-tree-toggle-mixin.js +151 -0
- package/src/vaadin-grid-tree-toggle.d.ts +4 -27
- package/src/vaadin-grid-tree-toggle.js +9 -141
- package/web-types.json +98 -98
- package/web-types.lit.json +42 -42
|
@@ -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> =
|
|
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
|
*/
|
|
@@ -181,18 +76,6 @@ export const DataProviderMixin = (superClass) =>
|
|
|
181
76
|
reflectToAttribute: true,
|
|
182
77
|
},
|
|
183
78
|
|
|
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
79
|
/**
|
|
197
80
|
* @protected
|
|
198
81
|
*/
|
|
@@ -244,12 +127,50 @@ export const DataProviderMixin = (superClass) =>
|
|
|
244
127
|
return ['_sizeChanged(size)', '_expandedItemsChanged(expandedItems.*)'];
|
|
245
128
|
}
|
|
246
129
|
|
|
130
|
+
constructor() {
|
|
131
|
+
super();
|
|
132
|
+
|
|
133
|
+
/** @type {DataProviderController} */
|
|
134
|
+
this._dataProviderController = new DataProviderController(this, {
|
|
135
|
+
size: this.size,
|
|
136
|
+
pageSize: this.pageSize,
|
|
137
|
+
isExpanded: this._isExpanded.bind(this),
|
|
138
|
+
dataProvider: this.dataProvider ? this.dataProvider.bind(this) : null,
|
|
139
|
+
dataProviderParams: () => {
|
|
140
|
+
return {
|
|
141
|
+
sortOrders: this._mapSorters(),
|
|
142
|
+
filters: this._mapFilters(),
|
|
143
|
+
};
|
|
144
|
+
},
|
|
145
|
+
});
|
|
146
|
+
|
|
147
|
+
this._dataProviderController.addEventListener('page-requested', this._onDataProviderPageRequested.bind(this));
|
|
148
|
+
this._dataProviderController.addEventListener('page-received', this._onDataProviderPageReceived.bind(this));
|
|
149
|
+
this._dataProviderController.addEventListener('page-loaded', this._onDataProviderPageLoaded.bind(this));
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* @protected
|
|
154
|
+
* @deprecated since 24.3 and will be removed in Vaadin 25.
|
|
155
|
+
*/
|
|
156
|
+
get _cache() {
|
|
157
|
+
console.warn('<vaadin-grid> The `_cache` property is deprecated and will be removed in Vaadin 25.');
|
|
158
|
+
return this._dataProviderController.rootCache;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* @protected
|
|
163
|
+
* @deprecated since 24.3 and will be removed in Vaadin 25.
|
|
164
|
+
*/
|
|
165
|
+
get _effectiveSize() {
|
|
166
|
+
console.warn('<vaadin-grid> The `_effectiveSize` property is deprecated and will be removed in Vaadin 25.');
|
|
167
|
+
return this._flatSize;
|
|
168
|
+
}
|
|
169
|
+
|
|
247
170
|
/** @private */
|
|
248
171
|
_sizeChanged(size) {
|
|
249
|
-
|
|
250
|
-
this.
|
|
251
|
-
this._cache.effectiveSize += delta;
|
|
252
|
-
this._effectiveSize = this._cache.effectiveSize;
|
|
172
|
+
this._dataProviderController.setSize(size);
|
|
173
|
+
this._flatSize = this._dataProviderController.flatSize;
|
|
253
174
|
}
|
|
254
175
|
|
|
255
176
|
/** @private */
|
|
@@ -267,22 +188,22 @@ export const DataProviderMixin = (superClass) =>
|
|
|
267
188
|
* @protected
|
|
268
189
|
*/
|
|
269
190
|
_getItem(index, el) {
|
|
270
|
-
if (index >= this.
|
|
191
|
+
if (index >= this._flatSize) {
|
|
271
192
|
return;
|
|
272
193
|
}
|
|
273
194
|
|
|
274
195
|
el.index = index;
|
|
275
|
-
|
|
276
|
-
const item =
|
|
196
|
+
|
|
197
|
+
const { item } = this._dataProviderController.getFlatIndexContext(index);
|
|
277
198
|
if (item) {
|
|
278
199
|
this.__updateLoading(el, false);
|
|
279
200
|
this._updateItem(el, item);
|
|
280
201
|
if (this._isExpanded(item)) {
|
|
281
|
-
|
|
202
|
+
this._dataProviderController.ensureFlatIndexHierarchy(index);
|
|
282
203
|
}
|
|
283
204
|
} else {
|
|
284
205
|
this.__updateLoading(el, true);
|
|
285
|
-
this.
|
|
206
|
+
this._dataProviderController.ensureFlatIndexLoaded(index);
|
|
286
207
|
}
|
|
287
208
|
}
|
|
288
209
|
|
|
@@ -322,8 +243,8 @@ export const DataProviderMixin = (superClass) =>
|
|
|
322
243
|
|
|
323
244
|
/** @private */
|
|
324
245
|
_expandedItemsChanged() {
|
|
325
|
-
this.
|
|
326
|
-
this.
|
|
246
|
+
this._dataProviderController.recalculateFlatSize();
|
|
247
|
+
this._flatSize = this._dataProviderController.flatSize;
|
|
327
248
|
this.__updateVisibleRows();
|
|
328
249
|
}
|
|
329
250
|
|
|
@@ -363,13 +284,8 @@ export const DataProviderMixin = (superClass) =>
|
|
|
363
284
|
* @return {number}
|
|
364
285
|
* @protected
|
|
365
286
|
*/
|
|
366
|
-
_getIndexLevel(index) {
|
|
367
|
-
|
|
368
|
-
let level = 0;
|
|
369
|
-
while (cache.parentCache) {
|
|
370
|
-
cache = cache.parentCache;
|
|
371
|
-
level += 1;
|
|
372
|
-
}
|
|
287
|
+
_getIndexLevel(index = 0) {
|
|
288
|
+
const { level } = this._dataProviderController.getFlatIndexContext(index);
|
|
373
289
|
return level;
|
|
374
290
|
}
|
|
375
291
|
|
|
@@ -377,105 +293,70 @@ export const DataProviderMixin = (superClass) =>
|
|
|
377
293
|
* @param {number} page
|
|
378
294
|
* @param {ItemCache} cache
|
|
379
295
|
* @protected
|
|
296
|
+
* @deprecated since 24.3 and will be removed in Vaadin 25.
|
|
380
297
|
*/
|
|
381
298
|
_loadPage(page, cache) {
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
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
|
-
}
|
|
299
|
+
console.warn('<vaadin-grid> The `_loadPage` method is deprecated and will be removed in Vaadin 25.');
|
|
300
|
+
this._dataProviderController.__loadCachePage(cache, page);
|
|
301
|
+
}
|
|
400
302
|
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
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
|
-
});
|
|
438
|
-
|
|
439
|
-
// If the grid is not loading anything, flush the debouncer immediately
|
|
440
|
-
if (!this._cache.isLoading()) {
|
|
441
|
-
this._debouncerApplyCachedData.flush();
|
|
442
|
-
}
|
|
303
|
+
/** @protected */
|
|
304
|
+
_onDataProviderPageRequested() {
|
|
305
|
+
this._setLoading(true);
|
|
306
|
+
}
|
|
443
307
|
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
308
|
+
/** @protected */
|
|
309
|
+
_onDataProviderPageReceived() {
|
|
310
|
+
// With the new items added, update the cache size and the grid's effective size
|
|
311
|
+
this._flatSize = this._dataProviderController.flatSize;
|
|
312
|
+
|
|
313
|
+
// After updating the cache, check if some of the expanded items should have sub-caches loaded
|
|
314
|
+
this._getRenderedRows().forEach((row) => {
|
|
315
|
+
this._dataProviderController.ensureFlatIndexHierarchy(row.index);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
this._hasData = true;
|
|
448
319
|
}
|
|
449
320
|
|
|
450
321
|
/** @protected */
|
|
451
|
-
_onDataProviderPageLoaded() {
|
|
322
|
+
_onDataProviderPageLoaded() {
|
|
323
|
+
// Schedule a debouncer to update the visible rows
|
|
324
|
+
this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
|
|
325
|
+
this._setLoading(false);
|
|
326
|
+
|
|
327
|
+
this._getRenderedRows().forEach((row) => {
|
|
328
|
+
const { item } = this._dataProviderController.getFlatIndexContext(row.index);
|
|
329
|
+
if (item) {
|
|
330
|
+
this._getItem(row.index, row);
|
|
331
|
+
}
|
|
332
|
+
});
|
|
452
333
|
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
334
|
+
this.__scrollToPendingIndexes();
|
|
335
|
+
});
|
|
336
|
+
|
|
337
|
+
// If the grid is not loading anything, flush the debouncer immediately
|
|
338
|
+
if (!this._dataProviderController.isLoading()) {
|
|
339
|
+
this._debouncerApplyCachedData.flush();
|
|
340
|
+
}
|
|
460
341
|
}
|
|
461
342
|
|
|
462
343
|
/**
|
|
463
344
|
* Clears the cached pages and reloads data from dataprovider when needed.
|
|
464
345
|
*/
|
|
465
346
|
clearCache() {
|
|
466
|
-
this.
|
|
467
|
-
this._cache.size = this.size || 0;
|
|
468
|
-
this._cache.updateSize();
|
|
347
|
+
this._dataProviderController.clearCache();
|
|
469
348
|
this._hasData = false;
|
|
470
349
|
this.__updateVisibleRows();
|
|
471
350
|
|
|
472
|
-
if (!this.
|
|
473
|
-
this.
|
|
351
|
+
if (!this._flatSize) {
|
|
352
|
+
this._dataProviderController.loadFirstPage();
|
|
474
353
|
}
|
|
475
354
|
}
|
|
476
355
|
|
|
477
356
|
/** @private */
|
|
478
357
|
_pageSizeChanged(pageSize, oldPageSize) {
|
|
358
|
+
this._dataProviderController.setPageSize(pageSize);
|
|
359
|
+
|
|
479
360
|
if (oldPageSize !== undefined && pageSize !== oldPageSize) {
|
|
480
361
|
this.clearCache();
|
|
481
362
|
}
|
|
@@ -483,7 +364,7 @@ export const DataProviderMixin = (superClass) =>
|
|
|
483
364
|
|
|
484
365
|
/** @protected */
|
|
485
366
|
_checkSize() {
|
|
486
|
-
if (this.size === undefined && this.
|
|
367
|
+
if (this.size === undefined && this._flatSize === 0) {
|
|
487
368
|
console.warn(
|
|
488
369
|
'The <vaadin-grid> needs the total number of items in' +
|
|
489
370
|
' order to display rows, which you can specify either by setting' +
|
|
@@ -495,6 +376,8 @@ export const DataProviderMixin = (superClass) =>
|
|
|
495
376
|
|
|
496
377
|
/** @private */
|
|
497
378
|
_dataProviderChanged(dataProvider, oldDataProvider) {
|
|
379
|
+
this._dataProviderController.setDataProvider(dataProvider ? dataProvider.bind(this) : null);
|
|
380
|
+
|
|
498
381
|
if (oldDataProvider !== undefined) {
|
|
499
382
|
this.clearCache();
|
|
500
383
|
}
|
|
@@ -513,7 +396,7 @@ export const DataProviderMixin = (superClass) =>
|
|
|
513
396
|
if (!this._hasData) {
|
|
514
397
|
// Load data before adding rows to make sure they have content when
|
|
515
398
|
// rendered for the first time.
|
|
516
|
-
this.
|
|
399
|
+
this._dataProviderController.loadFirstPage();
|
|
517
400
|
}
|
|
518
401
|
}
|
|
519
402
|
|
|
@@ -563,39 +446,15 @@ export const DataProviderMixin = (superClass) =>
|
|
|
563
446
|
// ending up in a loading state. Try scrolling to the index until the target
|
|
564
447
|
// index stabilizes.
|
|
565
448
|
let targetIndex;
|
|
566
|
-
while (targetIndex !== (targetIndex = this.
|
|
449
|
+
while (targetIndex !== (targetIndex = this._dataProviderController.getFlatIndexByPath(indexes))) {
|
|
567
450
|
this._scrollToFlatIndex(targetIndex);
|
|
568
451
|
}
|
|
569
452
|
|
|
570
|
-
if (this.
|
|
453
|
+
if (this._dataProviderController.isLoading() || !this.clientHeight) {
|
|
571
454
|
this.__pendingScrollToIndexes = indexes;
|
|
572
455
|
}
|
|
573
456
|
}
|
|
574
457
|
|
|
575
|
-
/**
|
|
576
|
-
* Recursively returns the globally flat index of the item the given indexes point to.
|
|
577
|
-
* Each index in the array points to a sub-item of the previous index.
|
|
578
|
-
* Using `Infinity` as an index will point to the last item on the level.
|
|
579
|
-
*
|
|
580
|
-
* @param {!Array<number>} indexes
|
|
581
|
-
* @param {!ItemCache} cache
|
|
582
|
-
* @param {number} flatIndex
|
|
583
|
-
* @return {number}
|
|
584
|
-
* @private
|
|
585
|
-
*/
|
|
586
|
-
__getGlobalFlatIndex([levelIndex, ...subIndexes], cache = this._cache, flatIndex = 0) {
|
|
587
|
-
if (levelIndex === Infinity) {
|
|
588
|
-
// Treat Infinity as the last index on the level
|
|
589
|
-
levelIndex = cache.size - 1;
|
|
590
|
-
}
|
|
591
|
-
const flatIndexOnLevel = cache.getFlatIndex(levelIndex);
|
|
592
|
-
const subCache = cache.itemCaches[levelIndex];
|
|
593
|
-
if (subCache && subCache.effectiveSize && subIndexes.length) {
|
|
594
|
-
return this.__getGlobalFlatIndex(subIndexes, subCache, flatIndex + flatIndexOnLevel + 1);
|
|
595
|
-
}
|
|
596
|
-
return flatIndex + flatIndexOnLevel;
|
|
597
|
-
}
|
|
598
|
-
|
|
599
458
|
/** @private */
|
|
600
459
|
__scrollToPendingIndexes() {
|
|
601
460
|
if (this.__pendingScrollToIndexes && this.$.items.children.length) {
|
|
@@ -211,7 +211,7 @@ export const DragAndDropMixin = (superClass) =>
|
|
|
211
211
|
|
|
212
212
|
let row = e.composedPath().find((node) => node.localName === 'tr');
|
|
213
213
|
|
|
214
|
-
if (!this.
|
|
214
|
+
if (!this._flatSize || this.dropMode === DropMode.ON_GRID) {
|
|
215
215
|
// The grid is empty or "on-grid" drop mode was used, always default to "empty"
|
|
216
216
|
this._dropLocation = DropLocation.EMPTY;
|
|
217
217
|
} else if (!row || row.parentNode !== this.$.items) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import type { Constructor } from '@open-wc/dedupe-mixin';
|
|
7
|
+
import type { ControllerMixinClass } from '@vaadin/component-base/src/controller-mixin.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Fired when the `value` property changes.
|
|
11
|
+
*/
|
|
12
|
+
export type GridFilterValueChangedEvent = CustomEvent<{ value: string }>;
|
|
13
|
+
|
|
14
|
+
export interface GridFilterCustomEventMap {
|
|
15
|
+
'value-changed': GridFilterValueChangedEvent;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export interface GridFilterEventMap extends HTMLElementEventMap, GridFilterCustomEventMap {}
|
|
19
|
+
|
|
20
|
+
export declare function GridFilterElementMixin<T extends Constructor<HTMLElement>>(
|
|
21
|
+
base: T,
|
|
22
|
+
): Constructor<ControllerMixinClass> & Constructor<GridFilterElementMixinClass> & T;
|
|
23
|
+
|
|
24
|
+
declare class GridFilterElementMixinClass {
|
|
25
|
+
/**
|
|
26
|
+
* JS Path of the property in the item used for filtering the data.
|
|
27
|
+
*/
|
|
28
|
+
path: string | null | undefined;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Current filter value.
|
|
32
|
+
*/
|
|
33
|
+
value: string | null | undefined;
|
|
34
|
+
}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2016 - 2023 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
7
|
+
import { ControllerMixin } from '@vaadin/component-base/src/controller-mixin.js';
|
|
8
|
+
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
9
|
+
import { SlotController } from '@vaadin/component-base/src/slot-controller.js';
|
|
10
|
+
import { css, registerStyles } from '@vaadin/vaadin-themable-mixin';
|
|
11
|
+
|
|
12
|
+
registerStyles(
|
|
13
|
+
'vaadin-grid-filter',
|
|
14
|
+
css`
|
|
15
|
+
:host {
|
|
16
|
+
display: inline-flex;
|
|
17
|
+
max-width: 100%;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
::slotted(*) {
|
|
21
|
+
width: 100%;
|
|
22
|
+
box-sizing: border-box;
|
|
23
|
+
}
|
|
24
|
+
`,
|
|
25
|
+
{ moduleId: 'vaadin-grid-filter-styles' },
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* @polymerMixin
|
|
30
|
+
*
|
|
31
|
+
* @mixes ControllerMixin
|
|
32
|
+
*/
|
|
33
|
+
export const GridFilterElementMixin = (superClass) =>
|
|
34
|
+
class extends ControllerMixin(superClass) {
|
|
35
|
+
static get properties() {
|
|
36
|
+
return {
|
|
37
|
+
/**
|
|
38
|
+
* JS Path of the property in the item used for filtering the data.
|
|
39
|
+
*/
|
|
40
|
+
path: String,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Current filter value.
|
|
44
|
+
*/
|
|
45
|
+
value: {
|
|
46
|
+
type: String,
|
|
47
|
+
notify: true,
|
|
48
|
+
},
|
|
49
|
+
|
|
50
|
+
/** @private */
|
|
51
|
+
_textField: {
|
|
52
|
+
type: Object,
|
|
53
|
+
},
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
static get observers() {
|
|
58
|
+
return ['_filterChanged(path, value, _textField)'];
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/** @protected */
|
|
62
|
+
ready() {
|
|
63
|
+
super.ready();
|
|
64
|
+
|
|
65
|
+
this._filterController = new SlotController(this, '', 'vaadin-text-field', {
|
|
66
|
+
initializer: (field) => {
|
|
67
|
+
field.addEventListener('value-changed', (e) => {
|
|
68
|
+
this.value = e.detail.value;
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
this._textField = field;
|
|
72
|
+
},
|
|
73
|
+
});
|
|
74
|
+
this.addController(this._filterController);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/** @private */
|
|
78
|
+
_filterChanged(path, value, textField) {
|
|
79
|
+
if (path === undefined || value === undefined || !textField) {
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
if (this._previousValue === undefined && value === '') {
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
textField.value = value;
|
|
87
|
+
this._previousValue = value;
|
|
88
|
+
|
|
89
|
+
this._debouncerFilterChanged = Debouncer.debounce(this._debouncerFilterChanged, timeOut.after(200), () => {
|
|
90
|
+
this.dispatchEvent(new CustomEvent('filter-changed', { bubbles: true }));
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
focus() {
|
|
95
|
+
if (this._textField) {
|
|
96
|
+
this._textField.focus();
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|