@vaadin/combo-box 24.4.0-dev.4b20a0c55.3 → 24.4.0-rc1
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 +16 -14
- package/src/vaadin-combo-box-data-provider-mixin.js +117 -121
- package/src/vaadin-combo-box-item-mixin.js +1 -1
- package/src/vaadin-combo-box-mixin.js +63 -19
- package/src/vaadin-combo-box-scroller-mixin.js +40 -16
- package/src/vaadin-lit-combo-box-item.js +50 -0
- package/src/vaadin-lit-combo-box-light.js +58 -0
- package/src/vaadin-lit-combo-box-overlay.js +76 -0
- package/src/vaadin-lit-combo-box-scroller.js +59 -0
- package/src/vaadin-lit-combo-box.js +170 -0
- package/theme/lumo/vaadin-combo-box-item-styles.d.ts +5 -0
- package/theme/lumo/vaadin-combo-box-light.d.ts +3 -0
- package/theme/lumo/vaadin-combo-box-overlay-styles.d.ts +6 -0
- package/theme/lumo/vaadin-combo-box-styles.d.ts +2 -0
- package/theme/lumo/vaadin-combo-box.d.ts +4 -0
- package/theme/lumo/vaadin-lit-combo-box-light.d.ts +3 -0
- package/theme/lumo/vaadin-lit-combo-box-light.js +3 -0
- package/theme/lumo/vaadin-lit-combo-box.d.ts +4 -0
- package/theme/lumo/vaadin-lit-combo-box.js +4 -0
- package/theme/material/vaadin-combo-box-item-styles.d.ts +5 -0
- package/theme/material/vaadin-combo-box-light.d.ts +3 -0
- package/theme/material/vaadin-combo-box-overlay-styles.d.ts +4 -0
- package/theme/material/vaadin-combo-box-styles.d.ts +3 -0
- package/theme/material/vaadin-combo-box.d.ts +4 -0
- package/web-types.json +1188 -0
- package/web-types.lit.json +573 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vaadin/combo-box",
|
|
3
|
-
"version": "24.4.0-
|
|
3
|
+
"version": "24.4.0-rc1",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -26,7 +26,9 @@
|
|
|
26
26
|
"vaadin-*.d.ts",
|
|
27
27
|
"vaadin-*.js",
|
|
28
28
|
"web-types.json",
|
|
29
|
-
"web-types.lit.json"
|
|
29
|
+
"web-types.lit.json",
|
|
30
|
+
"!vaadin-lit-*.d.ts",
|
|
31
|
+
"!vaadin-lit-*.js"
|
|
30
32
|
],
|
|
31
33
|
"keywords": [
|
|
32
34
|
"Vaadin",
|
|
@@ -38,21 +40,21 @@
|
|
|
38
40
|
"dependencies": {
|
|
39
41
|
"@open-wc/dedupe-mixin": "^1.3.0",
|
|
40
42
|
"@polymer/polymer": "^3.0.0",
|
|
41
|
-
"@vaadin/a11y-base": "24.4.0-
|
|
42
|
-
"@vaadin/component-base": "24.4.0-
|
|
43
|
-
"@vaadin/field-base": "24.4.0-
|
|
44
|
-
"@vaadin/input-container": "24.4.0-
|
|
45
|
-
"@vaadin/item": "24.4.0-
|
|
46
|
-
"@vaadin/lit-renderer": "24.4.0-
|
|
47
|
-
"@vaadin/overlay": "24.4.0-
|
|
48
|
-
"@vaadin/vaadin-lumo-styles": "24.4.0-
|
|
49
|
-
"@vaadin/vaadin-material-styles": "24.4.0-
|
|
50
|
-
"@vaadin/vaadin-themable-mixin": "24.4.0-
|
|
43
|
+
"@vaadin/a11y-base": "24.4.0-rc1",
|
|
44
|
+
"@vaadin/component-base": "24.4.0-rc1",
|
|
45
|
+
"@vaadin/field-base": "24.4.0-rc1",
|
|
46
|
+
"@vaadin/input-container": "24.4.0-rc1",
|
|
47
|
+
"@vaadin/item": "24.4.0-rc1",
|
|
48
|
+
"@vaadin/lit-renderer": "24.4.0-rc1",
|
|
49
|
+
"@vaadin/overlay": "24.4.0-rc1",
|
|
50
|
+
"@vaadin/vaadin-lumo-styles": "24.4.0-rc1",
|
|
51
|
+
"@vaadin/vaadin-material-styles": "24.4.0-rc1",
|
|
52
|
+
"@vaadin/vaadin-themable-mixin": "24.4.0-rc1"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
55
|
"@esm-bundle/chai": "^4.3.4",
|
|
54
56
|
"@vaadin/testing-helpers": "^0.6.0",
|
|
55
|
-
"@vaadin/text-field": "24.4.0-
|
|
57
|
+
"@vaadin/text-field": "24.4.0-rc1",
|
|
56
58
|
"lit": "^3.0.0",
|
|
57
59
|
"sinon": "^13.0.2"
|
|
58
60
|
},
|
|
@@ -60,5 +62,5 @@
|
|
|
60
62
|
"web-types.json",
|
|
61
63
|
"web-types.lit.json"
|
|
62
64
|
],
|
|
63
|
-
"gitHead": "
|
|
65
|
+
"gitHead": "a81e3b927d44c56613fa4e1307494a2acc81005f"
|
|
64
66
|
}
|
|
@@ -3,8 +3,6 @@
|
|
|
3
3
|
* Copyright (c) 2015 - 2024 Vaadin Ltd.
|
|
4
4
|
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
5
|
*/
|
|
6
|
-
import { DataProviderController } from '@vaadin/component-base/src/data-provider-controller/data-provider-controller.js';
|
|
7
|
-
import { get } from '@vaadin/component-base/src/path-utils.js';
|
|
8
6
|
import { ComboBoxPlaceholder } from './vaadin-combo-box-placeholder.js';
|
|
9
7
|
|
|
10
8
|
/**
|
|
@@ -23,6 +21,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
23
21
|
type: Number,
|
|
24
22
|
value: 50,
|
|
25
23
|
observer: '_pageSizeChanged',
|
|
24
|
+
sync: true,
|
|
26
25
|
},
|
|
27
26
|
|
|
28
27
|
/**
|
|
@@ -32,6 +31,7 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
32
31
|
size: {
|
|
33
32
|
type: Number,
|
|
34
33
|
observer: '_sizeChanged',
|
|
34
|
+
sync: true,
|
|
35
35
|
},
|
|
36
36
|
|
|
37
37
|
/**
|
|
@@ -51,6 +51,14 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
51
51
|
dataProvider: {
|
|
52
52
|
type: Object,
|
|
53
53
|
observer: '_dataProviderChanged',
|
|
54
|
+
sync: true,
|
|
55
|
+
},
|
|
56
|
+
|
|
57
|
+
/** @private */
|
|
58
|
+
_pendingRequests: {
|
|
59
|
+
value: () => {
|
|
60
|
+
return {};
|
|
61
|
+
},
|
|
54
62
|
},
|
|
55
63
|
|
|
56
64
|
/** @private */
|
|
@@ -62,12 +70,6 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
62
70
|
__previousDataProviderFilter: {
|
|
63
71
|
type: String,
|
|
64
72
|
},
|
|
65
|
-
|
|
66
|
-
/** @private */
|
|
67
|
-
_hasData: {
|
|
68
|
-
type: Boolean,
|
|
69
|
-
value: false,
|
|
70
|
-
},
|
|
71
73
|
};
|
|
72
74
|
}
|
|
73
75
|
|
|
@@ -79,46 +81,20 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
79
81
|
];
|
|
80
82
|
}
|
|
81
83
|
|
|
82
|
-
constructor() {
|
|
83
|
-
super();
|
|
84
|
-
|
|
85
|
-
/** @type {DataProviderController} */
|
|
86
|
-
this._dataProviderController = new DataProviderController(this, {
|
|
87
|
-
size: this.size,
|
|
88
|
-
pageSize: this.pageSize,
|
|
89
|
-
getItemId: (item) => get(this.itemIdPath, item),
|
|
90
|
-
placeholder: this.__placeHolder,
|
|
91
|
-
dataProvider: this.dataProvider ? this.dataProvider.bind(this) : null,
|
|
92
|
-
dataProviderParams: () => ({ filter: this.filter }),
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
|
|
96
84
|
/** @protected */
|
|
97
85
|
ready() {
|
|
98
86
|
super.ready();
|
|
99
|
-
|
|
100
|
-
this._dataProviderController.addEventListener('page-requested', this.__onDataProviderPageRequested.bind(this));
|
|
101
|
-
this._dataProviderController.addEventListener('page-loaded', this.__onDataProviderPageLoaded.bind(this));
|
|
102
|
-
|
|
103
87
|
this._scroller.addEventListener('index-requested', (e) => {
|
|
104
88
|
if (!this._shouldFetchData()) {
|
|
105
89
|
return;
|
|
106
90
|
}
|
|
107
91
|
|
|
108
92
|
const index = e.detail.index;
|
|
109
|
-
const currentScrollerPos = e.detail.currentScrollerPos;
|
|
110
|
-
const allowedIndexRange = Math.floor(this.pageSize * 1.5);
|
|
111
|
-
|
|
112
|
-
// Ignores the indexes, which are being re-sent during scrolling reset,
|
|
113
|
-
// if the corresponding page is around the current scroller position.
|
|
114
|
-
// Otherwise, there might be a last pages duplicates, which cause the
|
|
115
|
-
// loading indicator hanging and blank items
|
|
116
|
-
if (this._shouldSkipIndex(index, allowedIndexRange, currentScrollerPos)) {
|
|
117
|
-
return;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
93
|
if (index !== undefined) {
|
|
121
|
-
this.
|
|
94
|
+
const page = this._getPageForIndex(index);
|
|
95
|
+
if (this._shouldLoadPage(page)) {
|
|
96
|
+
this._loadPage(page);
|
|
97
|
+
}
|
|
122
98
|
}
|
|
123
99
|
});
|
|
124
100
|
}
|
|
@@ -133,10 +109,11 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
133
109
|
if (this.__previousDataProviderFilter !== filter) {
|
|
134
110
|
this.__previousDataProviderFilter = filter;
|
|
135
111
|
|
|
136
|
-
this.
|
|
112
|
+
this.__keepOverlayOpened = true;
|
|
113
|
+
this._pendingRequests = {};
|
|
137
114
|
this.size = undefined;
|
|
138
115
|
this.clearCache();
|
|
139
|
-
this.
|
|
116
|
+
this.__keepOverlayOpened = false;
|
|
140
117
|
}
|
|
141
118
|
}
|
|
142
119
|
|
|
@@ -155,114 +132,110 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
155
132
|
return;
|
|
156
133
|
}
|
|
157
134
|
|
|
158
|
-
if (opened &&
|
|
159
|
-
this.
|
|
135
|
+
if (opened && this._shouldLoadPage(0)) {
|
|
136
|
+
this._loadPage(0);
|
|
160
137
|
}
|
|
161
138
|
}
|
|
162
139
|
|
|
163
140
|
/** @private */
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
);
|
|
170
|
-
}
|
|
141
|
+
_shouldLoadPage(page) {
|
|
142
|
+
if (this._forceNextRequest) {
|
|
143
|
+
this._forceNextRequest = false;
|
|
144
|
+
return true;
|
|
145
|
+
}
|
|
171
146
|
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
147
|
+
const loadedItem = this.filteredItems[page * this.pageSize];
|
|
148
|
+
if (loadedItem !== undefined) {
|
|
149
|
+
return loadedItem instanceof ComboBoxPlaceholder;
|
|
150
|
+
}
|
|
151
|
+
return this.size === undefined;
|
|
175
152
|
}
|
|
176
153
|
|
|
177
154
|
/** @private */
|
|
178
|
-
|
|
179
|
-
|
|
155
|
+
_loadPage(page) {
|
|
156
|
+
// Make sure same page isn't requested multiple times.
|
|
157
|
+
if (this._pendingRequests[page] || !this.dataProvider) {
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
180
160
|
|
|
181
|
-
|
|
161
|
+
const params = {
|
|
162
|
+
page,
|
|
163
|
+
pageSize: this.pageSize,
|
|
164
|
+
filter: this.filter,
|
|
165
|
+
};
|
|
182
166
|
|
|
183
|
-
|
|
184
|
-
this.
|
|
185
|
-
|
|
186
|
-
|
|
167
|
+
const callback = (items, size) => {
|
|
168
|
+
if (this._pendingRequests[page] !== callback) {
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
187
171
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
clearCache() {
|
|
192
|
-
if (!this.dataProvider) {
|
|
193
|
-
return;
|
|
194
|
-
}
|
|
172
|
+
const filteredItems = this.filteredItems ? [...this.filteredItems] : [];
|
|
173
|
+
filteredItems.splice(params.page * params.pageSize, items.length, ...items);
|
|
174
|
+
this.filteredItems = filteredItems;
|
|
195
175
|
|
|
196
|
-
|
|
176
|
+
if (!this.opened && !this._isInputFocused()) {
|
|
177
|
+
this._commitValue();
|
|
178
|
+
}
|
|
197
179
|
|
|
198
|
-
|
|
180
|
+
if (size !== undefined) {
|
|
181
|
+
this.size = size;
|
|
182
|
+
}
|
|
199
183
|
|
|
200
|
-
|
|
184
|
+
delete this._pendingRequests[page];
|
|
201
185
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
186
|
+
if (Object.keys(this._pendingRequests).length === 0) {
|
|
187
|
+
this.loading = false;
|
|
188
|
+
}
|
|
189
|
+
};
|
|
190
|
+
|
|
191
|
+
this._pendingRequests[page] = callback;
|
|
192
|
+
// Set the `loading` flag only after marking the request as pending
|
|
193
|
+
// to prevent the same page from getting requested multiple times
|
|
194
|
+
// as a result of `__loadingChanged` in the scroller which requests
|
|
195
|
+
// a virtualizer update which in turn may trigger a data provider page request.
|
|
196
|
+
this.loading = true;
|
|
197
|
+
this.dataProvider(params, callback);
|
|
205
198
|
}
|
|
206
199
|
|
|
207
200
|
/** @private */
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
// When the size update originates from the developer,
|
|
211
|
-
// sync the new size with the controller and trigger
|
|
212
|
-
// a content update to re-render the scroller.
|
|
213
|
-
if (rootCache.size !== size) {
|
|
214
|
-
rootCache.size = size;
|
|
215
|
-
this.requestContentUpdate();
|
|
216
|
-
}
|
|
201
|
+
_getPageForIndex(index) {
|
|
202
|
+
return Math.floor(index / this.pageSize);
|
|
217
203
|
}
|
|
218
204
|
|
|
219
205
|
/**
|
|
220
|
-
*
|
|
221
|
-
* @override
|
|
206
|
+
* Clears the cached pages and reloads data from dataprovider when needed.
|
|
222
207
|
*/
|
|
223
|
-
|
|
208
|
+
clearCache() {
|
|
224
209
|
if (!this.dataProvider) {
|
|
225
|
-
return
|
|
210
|
+
return;
|
|
226
211
|
}
|
|
227
212
|
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
if (rootCache.items !== items) {
|
|
233
|
-
rootCache.items = items;
|
|
234
|
-
this.requestContentUpdate();
|
|
213
|
+
this._pendingRequests = {};
|
|
214
|
+
const filteredItems = [];
|
|
215
|
+
for (let i = 0; i < (this.size || 0); i++) {
|
|
216
|
+
filteredItems.push(this.__placeHolder);
|
|
235
217
|
}
|
|
236
|
-
|
|
218
|
+
this.filteredItems = filteredItems;
|
|
237
219
|
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
// the controller received new data.
|
|
246
|
-
if ((this.size || 0) !== rootCache.size) {
|
|
247
|
-
this.size = rootCache.size;
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Sync the controller's items with the component.
|
|
251
|
-
// They can be out of sync after, for example,
|
|
252
|
-
// the controller received new data.
|
|
253
|
-
if (this.filteredItems !== rootCache.items) {
|
|
254
|
-
this.filteredItems = rootCache.items;
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Sync the controller's loading state with the component.
|
|
258
|
-
this.loading = this._dataProviderController.isLoading();
|
|
220
|
+
if (this._shouldFetchData()) {
|
|
221
|
+
this._forceNextRequest = false;
|
|
222
|
+
this._loadPage(0);
|
|
223
|
+
} else {
|
|
224
|
+
this._forceNextRequest = true;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
259
227
|
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
228
|
+
/** @private */
|
|
229
|
+
_sizeChanged(size = 0) {
|
|
230
|
+
const filteredItems = (this.filteredItems || []).slice(0, size);
|
|
231
|
+
for (let i = 0; i < size; i++) {
|
|
232
|
+
filteredItems[i] = filteredItems[i] !== undefined ? filteredItems[i] : this.__placeHolder;
|
|
263
233
|
}
|
|
234
|
+
this.filteredItems = filteredItems;
|
|
264
235
|
|
|
265
|
-
|
|
236
|
+
// Cleans up the redundant pending requests for pages > size
|
|
237
|
+
// Refers to https://github.com/vaadin/vaadin-flow-components/issues/229
|
|
238
|
+
this._flushPendingRequests(size);
|
|
266
239
|
}
|
|
267
240
|
|
|
268
241
|
/** @private */
|
|
@@ -271,8 +244,6 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
271
244
|
this.pageSize = oldPageSize;
|
|
272
245
|
throw new Error('`pageSize` value must be an integer > 0');
|
|
273
246
|
}
|
|
274
|
-
|
|
275
|
-
this._dataProviderController.setPageSize(pageSize);
|
|
276
247
|
this.clearCache();
|
|
277
248
|
}
|
|
278
249
|
|
|
@@ -282,7 +253,6 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
282
253
|
this.dataProvider = oldDataProvider;
|
|
283
254
|
});
|
|
284
255
|
|
|
285
|
-
this._dataProviderController.setDataProvider(dataProvider);
|
|
286
256
|
this.clearCache();
|
|
287
257
|
}
|
|
288
258
|
|
|
@@ -291,6 +261,8 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
291
261
|
if (this.items !== undefined && this.dataProvider !== undefined) {
|
|
292
262
|
restoreOldValueCallback();
|
|
293
263
|
throw new Error('Using `items` and `dataProvider` together is not supported');
|
|
264
|
+
} else if (this.dataProvider && !this.filteredItems) {
|
|
265
|
+
this.filteredItems = [];
|
|
294
266
|
}
|
|
295
267
|
}
|
|
296
268
|
|
|
@@ -309,4 +281,28 @@ export const ComboBoxDataProviderMixin = (superClass) =>
|
|
|
309
281
|
}
|
|
310
282
|
}
|
|
311
283
|
}
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* This method cleans up the page callbacks which refers to the
|
|
287
|
+
* non-existing pages, i.e. which item indexes are greater than the
|
|
288
|
+
* changed size.
|
|
289
|
+
* This case is basically happens when:
|
|
290
|
+
* 1. Users scroll fast to the bottom and combo box generates the
|
|
291
|
+
* redundant page request/callback
|
|
292
|
+
* 2. Server side uses undefined size lazy loading and suddenly reaches
|
|
293
|
+
* the exact size which is on the range edge
|
|
294
|
+
* (for default page size = 50, it will be 100, 200, 300, ...).
|
|
295
|
+
* @param size the new size of items
|
|
296
|
+
* @private
|
|
297
|
+
*/
|
|
298
|
+
_flushPendingRequests(size) {
|
|
299
|
+
if (this._pendingRequests) {
|
|
300
|
+
const lastPage = Math.ceil(size / this.pageSize);
|
|
301
|
+
Object.entries(this._pendingRequests).forEach(([page, callback]) => {
|
|
302
|
+
if (parseInt(page) >= lastPage) {
|
|
303
|
+
callback([], size);
|
|
304
|
+
}
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
312
308
|
};
|
|
@@ -60,7 +60,7 @@ export const ComboBoxItemMixin = (superClass) =>
|
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
static get observers() {
|
|
63
|
-
return ['__rendererOrItemChanged(renderer, index, item
|
|
63
|
+
return ['__rendererOrItemChanged(renderer, index, item, selected, focused)', '__updateLabel(label, renderer)'];
|
|
64
64
|
}
|
|
65
65
|
|
|
66
66
|
static get observedAttributes() {
|
|
@@ -71,6 +71,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
71
71
|
notify: true,
|
|
72
72
|
value: false,
|
|
73
73
|
reflectToAttribute: true,
|
|
74
|
+
sync: true,
|
|
74
75
|
observer: '_openedChanged',
|
|
75
76
|
},
|
|
76
77
|
|
|
@@ -80,6 +81,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
80
81
|
*/
|
|
81
82
|
autoOpenDisabled: {
|
|
82
83
|
type: Boolean,
|
|
84
|
+
sync: true,
|
|
83
85
|
},
|
|
84
86
|
|
|
85
87
|
/**
|
|
@@ -104,7 +106,10 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
104
106
|
* - `model.item` The item.
|
|
105
107
|
* @type {ComboBoxRenderer | undefined}
|
|
106
108
|
*/
|
|
107
|
-
renderer:
|
|
109
|
+
renderer: {
|
|
110
|
+
type: Object,
|
|
111
|
+
sync: true,
|
|
112
|
+
},
|
|
108
113
|
|
|
109
114
|
/**
|
|
110
115
|
* A full set of items to filter the visible options from.
|
|
@@ -113,6 +118,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
113
118
|
*/
|
|
114
119
|
items: {
|
|
115
120
|
type: Array,
|
|
121
|
+
sync: true,
|
|
116
122
|
observer: '_itemsChanged',
|
|
117
123
|
},
|
|
118
124
|
|
|
@@ -138,6 +144,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
138
144
|
filteredItems: {
|
|
139
145
|
type: Array,
|
|
140
146
|
observer: '_filteredItemsChanged',
|
|
147
|
+
sync: true,
|
|
141
148
|
},
|
|
142
149
|
|
|
143
150
|
/**
|
|
@@ -154,6 +161,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
154
161
|
type: Boolean,
|
|
155
162
|
value: false,
|
|
156
163
|
reflectToAttribute: true,
|
|
164
|
+
sync: true,
|
|
157
165
|
},
|
|
158
166
|
|
|
159
167
|
/**
|
|
@@ -164,6 +172,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
164
172
|
type: Number,
|
|
165
173
|
observer: '_focusedIndexChanged',
|
|
166
174
|
value: -1,
|
|
175
|
+
sync: true,
|
|
167
176
|
},
|
|
168
177
|
|
|
169
178
|
/**
|
|
@@ -174,6 +183,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
174
183
|
type: String,
|
|
175
184
|
value: '',
|
|
176
185
|
notify: true,
|
|
186
|
+
sync: true,
|
|
177
187
|
},
|
|
178
188
|
|
|
179
189
|
/**
|
|
@@ -183,6 +193,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
183
193
|
selectedItem: {
|
|
184
194
|
type: Object,
|
|
185
195
|
notify: true,
|
|
196
|
+
sync: true,
|
|
186
197
|
},
|
|
187
198
|
|
|
188
199
|
/**
|
|
@@ -199,6 +210,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
199
210
|
type: String,
|
|
200
211
|
value: 'label',
|
|
201
212
|
observer: '_itemLabelPathChanged',
|
|
213
|
+
sync: true,
|
|
202
214
|
},
|
|
203
215
|
|
|
204
216
|
/**
|
|
@@ -214,6 +226,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
214
226
|
itemValuePath: {
|
|
215
227
|
type: String,
|
|
216
228
|
value: 'value',
|
|
229
|
+
sync: true,
|
|
217
230
|
},
|
|
218
231
|
|
|
219
232
|
/**
|
|
@@ -223,7 +236,10 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
223
236
|
* `dataProvider` callback).
|
|
224
237
|
* @attr {string} item-id-path
|
|
225
238
|
*/
|
|
226
|
-
itemIdPath:
|
|
239
|
+
itemIdPath: {
|
|
240
|
+
type: String,
|
|
241
|
+
sync: true,
|
|
242
|
+
},
|
|
227
243
|
|
|
228
244
|
/**
|
|
229
245
|
* @type {!HTMLElement | undefined}
|
|
@@ -240,27 +256,38 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
240
256
|
*/
|
|
241
257
|
_dropdownItems: {
|
|
242
258
|
type: Array,
|
|
259
|
+
sync: true,
|
|
243
260
|
},
|
|
244
261
|
|
|
245
262
|
/** @private */
|
|
246
263
|
_closeOnBlurIsPrevented: Boolean,
|
|
247
264
|
|
|
248
265
|
/** @private */
|
|
249
|
-
_scroller:
|
|
266
|
+
_scroller: {
|
|
267
|
+
type: Object,
|
|
268
|
+
sync: true,
|
|
269
|
+
},
|
|
250
270
|
|
|
251
271
|
/** @private */
|
|
252
272
|
_overlayOpened: {
|
|
253
273
|
type: Boolean,
|
|
274
|
+
sync: true,
|
|
254
275
|
observer: '_overlayOpenedChanged',
|
|
255
276
|
},
|
|
277
|
+
|
|
278
|
+
/** @private */
|
|
279
|
+
__keepOverlayOpened: {
|
|
280
|
+
type: Boolean,
|
|
281
|
+
sync: true,
|
|
282
|
+
},
|
|
256
283
|
};
|
|
257
284
|
}
|
|
258
285
|
|
|
259
286
|
static get observers() {
|
|
260
287
|
return [
|
|
261
288
|
'_selectedItemChanged(selectedItem, itemValuePath, itemLabelPath)',
|
|
262
|
-
'_openedOrItemsChanged(opened, _dropdownItems, loading,
|
|
263
|
-
'_updateScroller(_scroller, _dropdownItems, opened, loading, selectedItem, itemIdPath, _focusedIndex, renderer,
|
|
289
|
+
'_openedOrItemsChanged(opened, _dropdownItems, loading, __keepOverlayOpened)',
|
|
290
|
+
'_updateScroller(_scroller, _dropdownItems, opened, loading, selectedItem, itemIdPath, _focusedIndex, renderer, _theme)',
|
|
264
291
|
];
|
|
265
292
|
}
|
|
266
293
|
|
|
@@ -413,6 +440,18 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
413
440
|
}
|
|
414
441
|
}
|
|
415
442
|
|
|
443
|
+
/**
|
|
444
|
+
* Override LitElement lifecycle callback to handle filter property change.
|
|
445
|
+
* @param {Object} props
|
|
446
|
+
*/
|
|
447
|
+
updated(props) {
|
|
448
|
+
super.updated(props);
|
|
449
|
+
|
|
450
|
+
if (props.has('filter')) {
|
|
451
|
+
this._filterChanged(this.filter);
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
|
|
416
455
|
/** @private */
|
|
417
456
|
_initOverlay() {
|
|
418
457
|
const overlay = this.$.overlay;
|
|
@@ -441,25 +480,23 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
441
480
|
* @protected
|
|
442
481
|
*/
|
|
443
482
|
_initScroller(host) {
|
|
444
|
-
const
|
|
483
|
+
const scroller = document.createElement(`${this._tagNamePrefix}-scroller`);
|
|
484
|
+
|
|
485
|
+
scroller.owner = host || this;
|
|
486
|
+
scroller.getItemLabel = this._getItemLabel.bind(this);
|
|
487
|
+
scroller.addEventListener('selection-changed', this._boundOverlaySelectedItemChanged);
|
|
445
488
|
|
|
446
489
|
const overlay = this._overlayElement;
|
|
447
490
|
|
|
448
491
|
overlay.renderer = (root) => {
|
|
449
|
-
if (!root.
|
|
450
|
-
root.appendChild(
|
|
492
|
+
if (!root.innerHTML) {
|
|
493
|
+
root.appendChild(scroller);
|
|
451
494
|
}
|
|
452
495
|
};
|
|
453
496
|
|
|
454
497
|
// Ensure the scroller is rendered
|
|
455
498
|
overlay.requestContentUpdate();
|
|
456
499
|
|
|
457
|
-
const scroller = overlay.querySelector(scrollerTag);
|
|
458
|
-
|
|
459
|
-
scroller.owner = host || this;
|
|
460
|
-
scroller.getItemLabel = this._getItemLabel.bind(this);
|
|
461
|
-
scroller.addEventListener('selection-changed', this._boundOverlaySelectedItemChanged);
|
|
462
|
-
|
|
463
500
|
// Trigger the observer to set properties
|
|
464
501
|
this._scroller = scroller;
|
|
465
502
|
}
|
|
@@ -483,6 +520,17 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
483
520
|
renderer,
|
|
484
521
|
theme,
|
|
485
522
|
});
|
|
523
|
+
|
|
524
|
+
// NOTE: in PolylitMixin, setProperties() waits for `hasUpdated` to be set.
|
|
525
|
+
// This means for the first opening, properties won't be set synchronously.
|
|
526
|
+
// Call `performUpdate()` in this case to mimic the Polymer version logic.
|
|
527
|
+
if (scroller.performUpdate && !scroller.hasUpdated) {
|
|
528
|
+
try {
|
|
529
|
+
scroller.performUpdate();
|
|
530
|
+
} catch (_) {
|
|
531
|
+
// Suppress errors in synchronous tests for pre-opened combo-box.
|
|
532
|
+
}
|
|
533
|
+
}
|
|
486
534
|
}
|
|
487
535
|
}
|
|
488
536
|
|
|
@@ -490,7 +538,7 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
490
538
|
_openedOrItemsChanged(opened, items, loading, keepOverlayOpened) {
|
|
491
539
|
// Close the overlay if there are no items to display.
|
|
492
540
|
// See https://github.com/vaadin/vaadin-combo-box/pull/964
|
|
493
|
-
this._overlayOpened =
|
|
541
|
+
this._overlayOpened = opened && (keepOverlayOpened || loading || !!(items && items.length));
|
|
494
542
|
}
|
|
495
543
|
|
|
496
544
|
/** @private */
|
|
@@ -1126,10 +1174,6 @@ export const ComboBoxMixin = (subclass) =>
|
|
|
1126
1174
|
this.items = oldItems;
|
|
1127
1175
|
});
|
|
1128
1176
|
|
|
1129
|
-
if (this.dataProvider) {
|
|
1130
|
-
return;
|
|
1131
|
-
}
|
|
1132
|
-
|
|
1133
1177
|
if (items) {
|
|
1134
1178
|
this.filteredItems = items.slice(0);
|
|
1135
1179
|
} else if (oldItems) {
|