Skip to content

Commit 5532750

Browse files
authored
DataGrid: Fix the "Cannot read properties of undefined (reading 'values')" error that occurs when adding a row to the second page if initial row values are specified in onInitNewRow (T1274123) (#32515)
1 parent d1c5c81 commit 5532750

8 files changed

Lines changed: 454 additions & 116 deletions

File tree

e2e/testcafe-devextreme/tests/dataGrid/common/editing.ts

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2957,3 +2957,97 @@ test('The onEditorPreparing event should be called once after clicking on a cell
29572957
delete (window as any).onEditorPreparingCallArgs;
29582958
})();
29592959
});
2960+
2961+
test('Adding rows to a second page should work correctly when initial row values ​​are specified in the onInitNewRow method (T1274123)', async (t) => {
2962+
// arrange
2963+
const dataGrid = new DataGrid('#container');
2964+
const addAndSaveData = async () => {
2965+
// act
2966+
await dataGrid.apiAddRow();
2967+
2968+
const editPopup = dataGrid.getEditPopup();
2969+
2970+
// assert
2971+
await t
2972+
.expect(editPopup.isVisible())
2973+
.ok();
2974+
2975+
// act
2976+
await dataGrid.apiSaveEditData();
2977+
2978+
// assert
2979+
await t
2980+
.expect(dataGrid.isReady())
2981+
.ok()
2982+
.expect(editPopup.isVisible())
2983+
.notOk();
2984+
};
2985+
2986+
await t.expect(dataGrid.isReady()).ok();
2987+
2988+
// act
2989+
await dataGrid.apiPageIndex(1);
2990+
await t.expect(dataGrid.isReady()).ok();
2991+
2992+
// assert
2993+
let visibleRows = await dataGrid.apiGetVisibleRows();
2994+
2995+
await t.expect(visibleRows.length)
2996+
.eql(10)
2997+
.expect(dataGrid.getDataCell(20, 0).element.textContent)
2998+
.eql('21');
2999+
3000+
// act
3001+
await addAndSaveData();
3002+
await addAndSaveData();
3003+
3004+
// assert
3005+
visibleRows = await dataGrid.apiGetVisibleRows();
3006+
3007+
await t
3008+
.expect(visibleRows.length)
3009+
.eql(12)
3010+
.expect(visibleRows[10].key)
3011+
.eql(31)
3012+
.expect(visibleRows[11].key)
3013+
.eql(32);
3014+
}).before(async () => {
3015+
await ClientFunction(() => {
3016+
(window as any).myData = new Array(30).fill(null).map((_, index) => ({ id: index + 1, text: `item ${index + 1}` }));
3017+
(window as any).myStore = new (window as any).DevExpress.data.ArrayStore({
3018+
key: 'id',
3019+
data: (window as any).myData,
3020+
});
3021+
})();
3022+
3023+
return createWidget('dxDataGrid', {
3024+
dataSource: {
3025+
key: 'id',
3026+
load(loadOptions) {
3027+
return (window as any).myStore.load(loadOptions);
3028+
},
3029+
totalCount() {
3030+
return (window as any).myStore.totalCount();
3031+
},
3032+
insert(values) {
3033+
if (values.id === 0) {
3034+
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
3035+
values.id = (window as any).myData.length + 1;
3036+
}
3037+
3038+
return (window as any).myStore.insert(values);
3039+
},
3040+
} as any,
3041+
columns: ['id', 'text'],
3042+
showBorders: true,
3043+
editing: {
3044+
mode: 'popup',
3045+
allowAdding: true,
3046+
},
3047+
onInitNewRow(e) {
3048+
e.data.id = 0;
3049+
e.data.text = 'test';
3050+
},
3051+
height: 300,
3052+
});
3053+
});
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import { jest } from '@jest/globals';
2+
import fx from '@js/common/core/animation/fx';
3+
import type { dxElementWrapper } from '@js/core/renderer';
4+
import $ from '@js/core/renderer';
5+
import type { Properties as DataGridProperties } from '@js/ui/data_grid';
6+
import DataGrid from '@js/ui/data_grid';
7+
import { DataGridModel } from '@ts/grids/data_grid/__tests__/__mock__/model/data_grid';
8+
import type { Controllers } from '@ts/grids/grid_core/m_types';
9+
10+
export interface DataGridInstance extends DataGrid {
11+
getController: <T extends keyof Controllers>(name: T) => Controllers[T];
12+
}
13+
14+
export const SELECTORS = {
15+
gridContainer: '#gridContainer',
16+
};
17+
18+
export const GRID_CONTAINER_ID = 'gridContainer';
19+
20+
export const createDataGrid = async (
21+
options: DataGridProperties = {},
22+
): Promise<{
23+
$container: dxElementWrapper;
24+
component: DataGridModel;
25+
instance: DataGridInstance;
26+
}> => new Promise((resolve) => {
27+
const $container = $('<div>')
28+
.attr('id', GRID_CONTAINER_ID)
29+
.appendTo(document.body);
30+
31+
const dataGridOptions: DataGridProperties = {
32+
keyExpr: 'id',
33+
...options,
34+
};
35+
36+
const instance = new DataGrid(
37+
$container.get(0) as HTMLDivElement,
38+
dataGridOptions,
39+
) as DataGridInstance;
40+
const component = new DataGridModel($container.get(0) as HTMLElement);
41+
42+
jest.runAllTimers();
43+
44+
resolve({
45+
$container,
46+
component,
47+
instance,
48+
});
49+
});
50+
51+
export const beforeTest = (): void => {
52+
fx.off = true;
53+
jest.useFakeTimers();
54+
};
55+
56+
export const afterTest = (): void => {
57+
const $container = $(SELECTORS.gridContainer);
58+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
59+
const dataGrid = ($container as any).dxDataGrid('instance') as DataGrid;
60+
61+
dataGrid?.dispose();
62+
$container.remove();
63+
jest.clearAllMocks();
64+
jest.useRealTimers();
65+
fx.off = false;
66+
};
67+
68+
export const flushAsync = async (): Promise<void> => {
69+
jest.runAllTimers();
70+
await Promise.resolve();
71+
};

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ interface HandleDataChangedArguments {
7070
error?: any;
7171
}
7272

73-
type UserData = Record<string, unknown>;
73+
export type UserData = Record<string, unknown>;
7474

7575
export interface Item {
7676
rowType: 'data' | 'group' | 'groupFooter' | 'detailAdaptive';

0 commit comments

Comments
 (0)