Skip to content

Commit ab905f2

Browse files
authored
Collection widget live update: fix correctionIndex applying in frameworks and after dataSource is updated at runtime (T1250900) (DevExpress#28738) (DevExpress#28748)
1 parent d45b84e commit ab905f2

File tree

2 files changed

+79
-15
lines changed

2 files changed

+79
-15
lines changed

packages/devextreme/js/__internal/ui/collection/m_collection_widget.live_update.ts

Lines changed: 25 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,15 @@ export default CollectionWidget.inherit({
1919
});
2020
},
2121

22-
ctor() {
23-
this.callBase.apply(this, arguments);
24-
25-
this._customizeStoreLoadOptions = (e) => {
26-
const dataController = this._dataController;
27-
28-
if (dataController.getDataSource() && !this._dataController.isLoaded()) {
29-
this._correctionIndex = 0;
30-
}
31-
if (this._correctionIndex && e.storeLoadOptions) {
32-
e.storeLoadOptions.skip += this._correctionIndex;
33-
}
34-
};
22+
_customizeStoreLoadOptions(e) {
23+
const dataController = this._dataController;
3524

36-
this._dataController?.on('customizeStoreLoadOptions', this._customizeStoreLoadOptions);
25+
if (dataController.getDataSource() && !this._dataController.isLoaded()) {
26+
this._correctionIndex = 0;
27+
}
28+
if (this._correctionIndex && e.storeLoadOptions) {
29+
e.storeLoadOptions.skip += this._correctionIndex;
30+
}
3731
},
3832

3933
reload() {
@@ -44,6 +38,7 @@ export default CollectionWidget.inherit({
4438
this.callBase();
4539
this._refreshItemsCache();
4640
this._correctionIndex = 0;
41+
this._subscribeLoadOptionsCustomization(true);
4742
},
4843

4944
_findItemElementByKey(key) {
@@ -146,7 +141,7 @@ export default CollectionWidget.inherit({
146141
},
147142

148143
_dispose() {
149-
this._dataController.off('customizeStoreLoadOptions', this._customizeStoreLoadOptions);
144+
this._subscribeLoadOptionsCustomization(false);
150145
this.callBase();
151146
},
152147

@@ -242,6 +237,19 @@ export default CollectionWidget.inherit({
242237
domAdapter.insertElement($container.get(0), $itemFrame.get(0), nextSiblingElement);
243238
},
244239

240+
_subscribeLoadOptionsCustomization(enable: boolean): void {
241+
if (!this._dataController) {
242+
return;
243+
}
244+
245+
if (enable) {
246+
this._correctionIndex = 0;
247+
this._dataController.on('customizeStoreLoadOptions', this._customizeStoreLoadOptions.bind(this));
248+
} else {
249+
this._dataController.off('customizeStoreLoadOptions', this._customizeStoreLoadOptions.bind(this));
250+
}
251+
},
252+
245253
_optionChanged(args) {
246254
switch (args.name) {
247255
case 'items': {
@@ -256,7 +264,9 @@ export default CollectionWidget.inherit({
256264
this.option('items', []);
257265
}
258266

267+
this._subscribeLoadOptionsCustomization(false);
259268
this.callBase(args);
269+
this._subscribeLoadOptionsCustomization(true);
260270
break;
261271
case 'repaintChangesOnly':
262272
break;

packages/devextreme/testing/tests/DevExpress.ui/collectionWidgetParts/liveUpdateTests.js

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -183,4 +183,58 @@ module('live update', {
183183
assert.strictEqual($items.first().text(), 'text 0 mark', 'the first item correctly updated');
184184
assert.strictEqual($items.last().text(), 'text 24 mark', 'the last item correctly updated');
185185
});
186+
187+
test('next page items should not be excessive skipped after dataSource runtime change and push remove (T1250900)', function(assert) {
188+
const newDataSource = new DataSource({
189+
load: () => helper.data.sort((a, b) => a.index - b.index),
190+
loadMode: 'raw',
191+
pageSize: 2,
192+
pushAggregationTimeout: 0,
193+
key: 'id'
194+
});
195+
helper.instance.option('dataSource', newDataSource);
196+
197+
let items = helper.getItems();
198+
assert.strictEqual(items.length, 2, '2 items on the first page');
199+
assert.strictEqual(items[0].id, 0, '0 item');
200+
assert.strictEqual(items[1].id, 1, '1st item');
201+
202+
newDataSource.store().push([{ type: 'remove', key: 0 }]);
203+
204+
items = helper.getItems();
205+
assert.strictEqual(items.length, 1, '1 item on the first page after remove');
206+
assert.strictEqual(items[0].id, 1, '1 item');
207+
208+
helper.instance.loadNextPage();
209+
210+
items = helper.getItems();
211+
assert.strictEqual(items.length, 3, '2 pages are loaded');
212+
assert.strictEqual(items[0].id, 1, '1 item');
213+
assert.strictEqual(items[1].id, 2, '2 item');
214+
assert.strictEqual(items[2].id, 3, '3 item');
215+
});
216+
217+
test('dataSource runtime change should be correct even if remove was pushed to the previous dataSource', function(assert) {
218+
const data = [...helper.data];
219+
helper.store.push([{ type: 'remove', key: 0 }]);
220+
221+
const newDataSource = new DataSource({
222+
load: (e) => data.sort((a, b) => a.index - b.index),
223+
loadMode: 'raw',
224+
pageSize: 2,
225+
pushAggregationTimeout: 0,
226+
key: 'id'
227+
});
228+
helper.instance.option('dataSource', newDataSource);
229+
230+
let items = helper.getItems();
231+
assert.strictEqual(items[0].id, 0, '0 item');
232+
assert.strictEqual(items[1].id, 1, '1 item');
233+
234+
helper.instance.loadNextPage();
235+
236+
items = helper.getItems();
237+
assert.strictEqual(items[2].id, 2, '2 item');
238+
assert.strictEqual(items[3].id, 3, '3 item');
239+
});
186240
});

0 commit comments

Comments
 (0)