Skip to content

Commit 6460943

Browse files
Update behavior for edit process (error with TextArea initial value) (#176)
* update behavior for edit flow * lint fix * Update CHANGELOG.md * Update screenshot --------- Co-authored-by: Mikhail Volkov <[email protected]>
1 parent 3922b74 commit 6460943

File tree

4 files changed

+108
-10
lines changed

4 files changed

+108
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Change Log
22

3-
## 1.8.0 (IN PROGRESS)
3+
## 1.8.0 (2024-11-21)
44

55
### Features / Enhancements
66

@@ -10,6 +10,7 @@
1010
- Added custom value to editable select field (#165)
1111
- Updated group expanding for empty cells (#169)
1212
- Added type check for text area (#172)
13+
- Updated behavior for edit process (error with TextArea initial value) (#176)
1314

1415
## 1.7.0 (2024-11-16)
1516

src/components/Table/hooks/useEditableData.test.ts

Lines changed: 66 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
import { Row } from '@tanstack/react-table';
22
import { act, renderHook } from '@testing-library/react';
33

4+
import { ColumnEditorType } from '@/types';
5+
import { createColumnAccessorFn, createColumnMeta } from '@/utils';
6+
47
import { useEditableData } from './useEditableData';
58

69
/**
@@ -22,8 +25,15 @@ describe('useEditableData', () => {
2225
...row,
2326
}) as any;
2427

28+
/**
29+
* Default Table
30+
*/
31+
const defaultTable = {
32+
getAllColumns: () => [],
33+
};
34+
2535
it('Should allow to start edit', async () => {
26-
const { result } = renderHook(() => useEditableData({ table: {} as any, onUpdateRow: jest.fn() }));
36+
const { result } = renderHook(() => useEditableData({ table: defaultTable as any, onUpdateRow: jest.fn() }));
2737

2838
const row = createRow({ id: '1', original: { name: 'abc' } });
2939
await act(async () => result.current.onStartEdit(row));
@@ -32,7 +42,7 @@ describe('useEditableData', () => {
3242
});
3343

3444
it('Should allow to cancel edit', async () => {
35-
const { result } = renderHook(() => useEditableData({ table: {} as any, onUpdateRow: jest.fn() }));
45+
const { result } = renderHook(() => useEditableData({ table: defaultTable as any, onUpdateRow: jest.fn() }));
3646

3747
const row = createRow({ id: '1', original: { name: 'abc' } });
3848

@@ -44,7 +54,7 @@ describe('useEditableData', () => {
4454
});
4555

4656
it('Should allow to change row data', async () => {
47-
const { result } = renderHook(() => useEditableData({ table: {} as any, onUpdateRow: jest.fn() }));
57+
const { result } = renderHook(() => useEditableData({ table: defaultTable as any, onUpdateRow: jest.fn() }));
4858

4959
const row = createRow({ id: '1', original: { name: 'abc' } });
5060

@@ -61,7 +71,7 @@ describe('useEditableData', () => {
6171

6272
it('Should allow to save row data', async () => {
6373
const onUpdateRow = jest.fn();
64-
const { result } = renderHook(() => useEditableData({ table: {} as any, onUpdateRow }));
74+
const { result } = renderHook(() => useEditableData({ table: defaultTable as any, onUpdateRow }));
6575

6676
const row = createRow({ id: '1', original: { name: 'abc' } });
6777

@@ -88,7 +98,7 @@ describe('useEditableData', () => {
8898

8999
it('Should reset saving state if update error', async () => {
90100
const onUpdateRow = jest.fn().mockRejectedValue(null);
91-
const { result } = renderHook(() => useEditableData({ table: {} as any, onUpdateRow }));
101+
const { result } = renderHook(() => useEditableData({ table: defaultTable as any, onUpdateRow }));
92102

93103
const row = createRow({ id: '1', original: { name: 'abc' } });
94104

@@ -109,4 +119,55 @@ describe('useEditableData', () => {
109119
expect(result.current.row).toEqual(row);
110120
expect(result.current.isSaving).toBeFalsy();
111121
});
122+
123+
it('Should allow to start edit and replace value for TextArea editors', async () => {
124+
const columns = [
125+
{
126+
id: 'name',
127+
accessorFn: createColumnAccessorFn('name'),
128+
columnDef: {
129+
meta: createColumnMeta({
130+
editable: false,
131+
}),
132+
},
133+
},
134+
{
135+
id: 'value',
136+
accessorFn: createColumnAccessorFn('value'),
137+
columnDef: {
138+
meta: createColumnMeta({
139+
editable: true,
140+
editor: {
141+
type: ColumnEditorType.NUMBER,
142+
},
143+
}),
144+
},
145+
},
146+
{
147+
id: 'text',
148+
accessorFn: createColumnAccessorFn('text'),
149+
columnDef: {
150+
meta: createColumnMeta({
151+
editable: true,
152+
editor: {
153+
type: ColumnEditorType.TEXTAREA,
154+
},
155+
}),
156+
},
157+
},
158+
];
159+
160+
const currentTable = {
161+
getAllColumns: () => columns,
162+
};
163+
164+
const { result } = renderHook(() => useEditableData({ table: currentTable as any, onUpdateRow: jest.fn() }));
165+
166+
const row = createRow({ id: '1', original: { name: 'abc', value: 10, text: 'text test\n' } });
167+
const expectedRow = createRow({ id: '1', original: { name: 'abc', value: 10, text: 'text test\\n' } });
168+
169+
await act(async () => result.current.onStartEdit(row));
170+
171+
expect(result.current.row).toEqual(expectedRow);
172+
});
112173
});

src/components/Table/hooks/useEditableData.ts

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1-
import { createRow, Row, Table } from '@tanstack/react-table';
1+
import { CoreRow, createRow, Row, Table } from '@tanstack/react-table';
22
import { useCallback, useMemo, useState } from 'react';
33

4+
import { ColumnEditorType } from '@/types';
5+
46
/**
57
* Use Editable Data
68
*/
@@ -24,9 +26,43 @@ export const useEditableData = <TData>({
2426
/**
2527
* Start Edit
2628
*/
27-
const onStartEdit = useCallback((row: Row<TData>) => {
28-
setRow(row);
29-
}, []);
29+
const onStartEdit = useCallback(
30+
(row: Row<TData>) => {
31+
/**
32+
* Columns
33+
*/
34+
const columns = table.getAllColumns();
35+
36+
/**
37+
* Update original row and replace initial value for text area editors
38+
*/
39+
const updatedOriginalRow = Object.entries(row.original as CoreRow<TData>).reduce<{ [key: string]: unknown }>(
40+
(acc, [key, value]) => {
41+
const foundColumn = columns.find((obj) => obj.id === key);
42+
43+
/**
44+
* Update text area value
45+
*/
46+
if (
47+
foundColumn?.columnDef.meta?.editable &&
48+
foundColumn?.columnDef.meta?.editor?.type === ColumnEditorType.TEXTAREA
49+
) {
50+
acc[key] = value.replaceAll('\n', '\\n');
51+
} else {
52+
acc[key] = value;
53+
}
54+
return acc;
55+
},
56+
{}
57+
);
58+
59+
/**
60+
* Set row with updated original row option
61+
*/
62+
setRow(createRow(table, row.id, updatedOriginalRow as TData, row.index, row.depth));
63+
},
64+
[table]
65+
);
3066

3167
/**
3268
* Cancel Edit

src/img/dashboard.png

76.3 KB
Loading

0 commit comments

Comments
 (0)