Skip to content

Commit 8dd59ef

Browse files
author
Alyar
committed
DataGrid: Fix detail grid reloading data when collapsed master row reenters viewport with virtual row rendering (T1326188)
1 parent e10e1db commit 8dd59ef

File tree

4 files changed

+123
-5
lines changed

4 files changed

+123
-5
lines changed
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
import { ClientFunction } from 'testcafe';
2+
import DataGrid from 'devextreme-testcafe-models/dataGrid';
3+
import url from '../../../../helpers/getPageUrl';
4+
import { createWidget } from '../../../../helpers/createWidget';
5+
6+
const getDetailGridLoadCount = ClientFunction(() => (window as any).detailGridLoadCount as number);
7+
8+
fixture.disablePageReloads`Master detail.Functional`
9+
.page(url(__dirname, '../../../container.html'));
10+
11+
test('Detail grid should not reload data when the collapsed master row reenters the viewport with standard scrolling and virtual row rendering (T1326188)', async (t) => {
12+
// arrange
13+
const dataGrid = new DataGrid('#container');
14+
15+
await t.expect(dataGrid.isReady()).ok();
16+
17+
// act - expand the master row
18+
await t.click(dataGrid.getDataRow(0).getCommandCell(0).element);
19+
20+
let detailGrid = dataGrid.getMasterRow(0).getDataGrid();
21+
22+
// assert
23+
await t
24+
.expect(dataGrid.getDataRow(0).isExpanded)
25+
.ok()
26+
.expect(detailGrid.element.exists)
27+
.ok()
28+
.expect(getDetailGridLoadCount())
29+
.eql(1);
30+
31+
// act - collapse the master row
32+
await t.click(dataGrid.getDataRow(0).getCommandCell(0).element);
33+
34+
// assert
35+
await t
36+
.expect(dataGrid.getDataRow(0).isExpanded)
37+
.notOk()
38+
.expect(detailGrid.element.visible)
39+
.notOk()
40+
.expect(getDetailGridLoadCount())
41+
.eql(1);
42+
43+
// act
44+
await dataGrid.scrollTo(t, { y: 5000 });
45+
46+
// assert
47+
await t
48+
.expect(dataGrid.getScrollTop())
49+
.gt(0, 'grid should have scrolled down');
50+
51+
// act
52+
await dataGrid.scrollTo(t, { y: 0 });
53+
54+
detailGrid = dataGrid.getMasterRow(0).getDataGrid();
55+
56+
// assert
57+
await t
58+
.expect(dataGrid.getScrollTop())
59+
.eql(0, 'grid should have scrolled back to top')
60+
.expect(detailGrid.element.exists)
61+
.notOk()
62+
.expect(getDetailGridLoadCount())
63+
.eql(1, 'Detail grid data should not be reloaded after scrolling back to the collapsed master row');
64+
}).before(async () => {
65+
await ClientFunction(() => {
66+
(window as any).detailGridLoadCount = 0;
67+
})();
68+
69+
return createWidget('dxDataGrid', {
70+
dataSource: [...new Array(200)].map((_, index) => ({
71+
id: index,
72+
text: `item ${index}`,
73+
})),
74+
keyExpr: 'id',
75+
height: 400,
76+
scrolling: {
77+
mode: 'standard',
78+
rowRenderingMode: 'virtual',
79+
// @ts-expect-error private option
80+
updateTimeout: 0,
81+
useNative: false,
82+
},
83+
paging: {
84+
enabled: false,
85+
},
86+
columns: ['id', 'text'],
87+
masterDetail: {
88+
enabled: true,
89+
template(container) {
90+
($('<div>') as any)
91+
.dxDataGrid({
92+
keyExpr: 'id',
93+
height: 180,
94+
columns: ['id', 'text'],
95+
dataSource: {
96+
load() {
97+
((window as any).detailGridLoadCount as number) += 1;
98+
99+
return [
100+
{ id: 1, text: 'detail 1' },
101+
{ id: 2, text: 'detail 2' },
102+
];
103+
},
104+
key: 'id',
105+
} as any,
106+
})
107+
.appendTo(container);
108+
},
109+
},
110+
});
111+
}).after(async () => ClientFunction(() => {
112+
delete (window as any).detailGridLoadCount;
113+
})());

e2e/testcafe-devextreme/tests/dataGrid/common/masterDetail.ts renamed to e2e/testcafe-devextreme/tests/dataGrid/common/masterDetail/visual.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { ClientFunction } from 'testcafe';
22
import { createScreenshotsComparer } from 'devextreme-screenshot-comparer';
33
import DataGrid from 'devextreme-testcafe-models/dataGrid';
4-
import url from '../../../helpers/getPageUrl';
5-
import { createWidget } from '../../../helpers/createWidget';
6-
import { testScreenshot } from '../../../helpers/themeUtils';
4+
import url from '../../../../helpers/getPageUrl';
5+
import { createWidget } from '../../../../helpers/createWidget';
6+
import { testScreenshot } from '../../../../helpers/themeUtils';
77

8-
fixture.disablePageReloads`Master detail`
9-
.page(url(__dirname, '../../container.html'));
8+
fixture.disablePageReloads`Master detail.Visual`
9+
.page(url(__dirname, '../../../container.html'));
1010

1111
// visual: material.blue.light
1212
// visual: generic.light

packages/devextreme/js/__internal/grids/grid_core/data_controller/m_data_controller.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,10 @@ export class DataController extends DataHelperMixin(modules.Controller) {
17911791
public isViewportChanging(): boolean {
17921792
return false;
17931793
}
1794+
1795+
public resetCachedProcessedItems(): void {
1796+
this._cachedProcessedItems = null;
1797+
}
17941798
}
17951799
export const dataControllerModule: Module = {
17961800
defaultOptions() {

packages/devextreme/js/__internal/grids/grid_core/master_detail/m_master_detail.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export const dataMasterDetailExtenderMixin = (Base: ModuleType<DataController>)
118118
changeType: 'update',
119119
rowIndices: that._getRowIndicesForExpand(key),
120120
});
121+
that.resetCachedProcessedItems();
121122

122123
// @ts-expect-error
123124
result = new Deferred().resolve();

0 commit comments

Comments
 (0)