@lminii/material-react-table 4.0.0 → 4.0.1
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/README.md +234 -234
- package/locales/ja/index.d.mts +0 -3
- package/locales/ja/index.d.ts +0 -3
- package/locales/ja/package.json +0 -6
- package/package.json +147 -147
- package/skills/README.md +81 -81
- package/skills/composable-components/SKILL.md +189 -189
- package/skills/customization/SKILL.md +190 -190
- package/skills/drag-and-drop-ordering/SKILL.md +227 -227
- package/skills/editing/SKILL.md +243 -243
- package/skills/filtering/SKILL.md +213 -213
- package/skills/getting-started/SKILL.md +213 -213
- package/skills/localization/SKILL.md +182 -182
- package/skills/migrate-v3-to-v4/SKILL.md +161 -161
- package/skills/state-and-server-data/SKILL.md +200 -200
- package/skills/virtualization/SKILL.md +203 -203
package/skills/editing/SKILL.md
CHANGED
|
@@ -1,243 +1,243 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: editing
|
|
3
|
-
description: >
|
|
4
|
-
Add create, update, and inline editing to Material React Table V4 with enableEditing, editDisplayMode (modal, row, cell, table, custom), createDisplayMode, onEditingRowSave and onCreatingRowSave with exitEditingMode, table.setEditingRow, table.setCreatingRow, muiEditTextFieldProps validation, editVariant select, and the Edit column slot. Load for CRUD tables, editable cells, row forms in a dialog, or when saved values never reach the callback.
|
|
5
|
-
metadata:
|
|
6
|
-
type: framework
|
|
7
|
-
library: '@lminii/material-react-table'
|
|
8
|
-
library_version: '4.0.0'
|
|
9
|
-
framework: react
|
|
10
|
-
requires:
|
|
11
|
-
- getting-started
|
|
12
|
-
- customization
|
|
13
|
-
sources:
|
|
14
|
-
- 'lminii/material-react-table:apps/material-react-table-docs/pages/docs/guides/editing.mdx'
|
|
15
|
-
- 'lminii/material-react-table:apps/material-react-table-docs/examples/editing-crud-modal/sandbox/src/TS.tsx'
|
|
16
|
-
- 'lminii/material-react-table:apps/material-react-table-docs/examples/editing-crud-cell/sandbox/src/TS.tsx'
|
|
17
|
-
- 'lminii/material-react-table:packages/material-react-table/src/components/inputs/MRT_EditCellTextField.tsx'
|
|
18
|
-
- 'lminii/material-react-table:packages/material-react-table/src/types.ts'
|
|
19
|
-
---
|
|
20
|
-
|
|
21
|
-
This skill builds on `getting-started` and `customization`. MRT renders the editing inputs and tracks which row or cell is being edited; persisting the values is always application code, wired through the save callbacks or the text field events.
|
|
22
|
-
|
|
23
|
-
## Setup
|
|
24
|
-
|
|
25
|
-
```tsx
|
|
26
|
-
const table = useMaterialReactTable({
|
|
27
|
-
columns,
|
|
28
|
-
data,
|
|
29
|
-
enableEditing: true,
|
|
30
|
-
editDisplayMode: 'modal', // default; also 'row' | 'cell' | 'table' | 'custom'
|
|
31
|
-
createDisplayMode: 'modal', // default; also 'row' | 'custom'
|
|
32
|
-
getRowId: (row) => row.id,
|
|
33
|
-
onEditingRowSave: async ({ values, table }) => {
|
|
34
|
-
await updateUser(values)
|
|
35
|
-
table.setEditingRow(null) // exit editing mode
|
|
36
|
-
},
|
|
37
|
-
onCreatingRowSave: async ({ values, table }) => {
|
|
38
|
-
await createUser(values)
|
|
39
|
-
table.setCreatingRow(null) // exit creating mode
|
|
40
|
-
},
|
|
41
|
-
renderRowActions: ({ row, table }) => (
|
|
42
|
-
<IconButton onClick={() => table.setEditingRow(row)}><EditIcon /></IconButton>
|
|
43
|
-
),
|
|
44
|
-
renderTopToolbarCustomActions: ({ table }) => (
|
|
45
|
-
<Button onClick={() => table.setCreatingRow(true)}>Create</Button>
|
|
46
|
-
),
|
|
47
|
-
})
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
`enableEditing` accepts a boolean or `(row) => boolean`, on the table and on each column. Column-level `enableEditing: false` renders a disabled field in the modal and the plain cell value in the other modes. The `editingRow`, `creatingRow`, and `editingCell` state slices hold the active row or cell; `table.setEditingRow`, `table.setCreatingRow`, and `table.setEditingCell` change them.
|
|
51
|
-
|
|
52
|
-
## Core Patterns
|
|
53
|
-
|
|
54
|
-
### Modal and row modes save through onEditingRowSave
|
|
55
|
-
|
|
56
|
-
```tsx
|
|
57
|
-
const handleSave: MRT_TableOptions<User>['onEditingRowSave'] = async ({ values, row, table, exitEditingMode }) => {
|
|
58
|
-
const errors = validateUser(values)
|
|
59
|
-
if (Object.values(errors).some(Boolean)) {
|
|
60
|
-
setValidationErrors(errors)
|
|
61
|
-
return // stay in editing mode
|
|
62
|
-
}
|
|
63
|
-
setValidationErrors({})
|
|
64
|
-
await updateUser({ ...row.original, ...values })
|
|
65
|
-
exitEditingMode() // same as table.setEditingRow(null)
|
|
66
|
-
}
|
|
67
|
-
```
|
|
68
|
-
|
|
69
|
-
`values` is a record keyed by column id, holding the edited text of every editable column. Nothing is written to `data`; the callback owns persistence. The callback may return a promise, and the `isSaving` state slice disables the save button and shows a spinner while it is true. `onEditingRowCancel` and `onCreatingRowCancel` fire when the user closes without saving, which is where validation errors get cleared.
|
|
70
|
-
|
|
71
|
-
### Cell and table modes save through the text field events
|
|
72
|
-
|
|
73
|
-
```tsx
|
|
74
|
-
const columns: MRT_ColumnDef<User>[] = [
|
|
75
|
-
{
|
|
76
|
-
accessorKey: 'email',
|
|
77
|
-
header: 'Email',
|
|
78
|
-
muiEditTextFieldProps: ({ cell, row }) => ({
|
|
79
|
-
type: 'email',
|
|
80
|
-
required: true,
|
|
81
|
-
error: !!validationErrors[cell.id],
|
|
82
|
-
helperText: validationErrors[cell.id],
|
|
83
|
-
onBlur: (event) => {
|
|
84
|
-
const value = event.currentTarget.value
|
|
85
|
-
setValidationErrors((prev) => ({ ...prev, [cell.id]: validateEmail(value) ? undefined : 'Invalid email' }))
|
|
86
|
-
setEditedUsers((prev) => ({ ...prev, [row.id]: { ...row.original, email: value } }))
|
|
87
|
-
},
|
|
88
|
-
}),
|
|
89
|
-
},
|
|
90
|
-
]
|
|
91
|
-
|
|
92
|
-
const table = useMaterialReactTable({
|
|
93
|
-
columns,
|
|
94
|
-
data,
|
|
95
|
-
enableEditing: true,
|
|
96
|
-
editDisplayMode: 'cell', // double-click a cell to edit it
|
|
97
|
-
})
|
|
98
|
-
```
|
|
99
|
-
|
|
100
|
-
In `'cell'` mode a double-click opens the field for that cell; in `'table'` mode every editable cell is a field at once. `onEditingRowSave` never fires in these modes. MRT calls your `onBlur` first, then stores the value in `row._valuesCache` and clears `editingCell`, so read `event.currentTarget.value` rather than `cell.getValue()`. Enter blurs the field. For single-click editing set `muiTableBodyCellProps` with an `onClick` that calls `table.setEditingCell(cell)` and focuses `table.refs.editInputRefs.current?.[column.id]`.
|
|
101
|
-
|
|
102
|
-
### Select inputs and custom Edit components
|
|
103
|
-
|
|
104
|
-
```tsx
|
|
105
|
-
{
|
|
106
|
-
accessorKey: 'state',
|
|
107
|
-
header: 'State',
|
|
108
|
-
editVariant: 'select',
|
|
109
|
-
editSelectOptions: usStates, // string[] or { label, value }[]
|
|
110
|
-
muiEditTextFieldProps: { select: true, required: true },
|
|
111
|
-
},
|
|
112
|
-
{
|
|
113
|
-
accessorKey: 'birthday',
|
|
114
|
-
header: 'Birthday',
|
|
115
|
-
Edit: ({ cell, column, row, table }) => (
|
|
116
|
-
<DatePicker
|
|
117
|
-
value={dayjs(cell.getValue<string>())}
|
|
118
|
-
onChange={(date) => {
|
|
119
|
-
row._valuesCache[column.id] = date?.toISOString()
|
|
120
|
-
if (table.getState().creatingRow?.id === row.id) table.setCreatingRow(row)
|
|
121
|
-
else table.setEditingRow(row)
|
|
122
|
-
}}
|
|
123
|
-
/>
|
|
124
|
-
),
|
|
125
|
-
},
|
|
126
|
-
```
|
|
127
|
-
|
|
128
|
-
`editSelectOptions` also accepts a callback receiving `cell`, `column`, `row`, and `table`. Select values save on change; text values save on blur. A custom `Edit` slot replaces the text field entirely, so it must write to `row._valuesCache[column.id]` and re-set the editing or creating row, otherwise the value never reaches `values` in the save callback.
|
|
129
|
-
|
|
130
|
-
### Customize the dialog and the create row
|
|
131
|
-
|
|
132
|
-
```tsx
|
|
133
|
-
import { MRT_EditActionButtons, createRow } from '@lminii/material-react-table'
|
|
134
|
-
|
|
135
|
-
const table = useMaterialReactTable({
|
|
136
|
-
columns,
|
|
137
|
-
data,
|
|
138
|
-
enableEditing: true,
|
|
139
|
-
positionCreatingRow: 'bottom', // 'top' (default), 'bottom', or a row index
|
|
140
|
-
renderEditRowDialogContent: ({ internalEditComponents, row, table }) => (
|
|
141
|
-
<>
|
|
142
|
-
<DialogTitle>Edit user</DialogTitle>
|
|
143
|
-
<DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>{internalEditComponents}</DialogContent>
|
|
144
|
-
<DialogActions><MRT_EditActionButtons table={table} row={row} variant="text" /></DialogActions>
|
|
145
|
-
</>
|
|
146
|
-
),
|
|
147
|
-
renderTopToolbarCustomActions: ({ table }) => (
|
|
148
|
-
<Button onClick={() => table.setCreatingRow(createRow(table, { id: crypto.randomUUID(), role: 'viewer' }))}>
|
|
149
|
-
Create with defaults
|
|
150
|
-
</Button>
|
|
151
|
-
),
|
|
152
|
-
})
|
|
153
|
-
```
|
|
154
|
-
|
|
155
|
-
`internalEditComponents` is the array of generated fields, one per column, so custom dialog content can reorder them or mix in other inputs. `renderCreateRowDialogContent` is the create counterpart. `table.setCreatingRow(true)` opens a blank row; `createRow(table, defaults)` seeds it. `muiEditRowDialogProps` reaches the Material UI `Dialog` itself. `editDisplayMode: 'custom'` and `createDisplayMode: 'custom'` keep the state slices and callbacks but render no MRT editing UI, for forms in a sidebar.
|
|
156
|
-
|
|
157
|
-
## Common Mistakes
|
|
158
|
-
|
|
159
|
-
### HIGH Forgetting to exit editing mode after saving
|
|
160
|
-
|
|
161
|
-
Wrong:
|
|
162
|
-
|
|
163
|
-
```tsx
|
|
164
|
-
onEditingRowSave: async ({ values }) => {
|
|
165
|
-
await updateUser(values)
|
|
166
|
-
}
|
|
167
|
-
```
|
|
168
|
-
|
|
169
|
-
Correct:
|
|
170
|
-
|
|
171
|
-
```tsx
|
|
172
|
-
onEditingRowSave: async ({ values, table }) => {
|
|
173
|
-
await updateUser(values)
|
|
174
|
-
table.setEditingRow(null)
|
|
175
|
-
}
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
MRT does not close the dialog or row on its own, so validation can keep it open. Call `exitEditingMode()` or `table.setEditingRow(null)` once the save succeeds, and the create counterpart `table.setCreatingRow(null)`.
|
|
179
|
-
|
|
180
|
-
Source: `docs/guides/editing.mdx`
|
|
181
|
-
|
|
182
|
-
### HIGH Expecting the data array to update itself
|
|
183
|
-
|
|
184
|
-
Wrong:
|
|
185
|
-
|
|
186
|
-
```tsx
|
|
187
|
-
editDisplayMode: 'cell',
|
|
188
|
-
// no muiEditTextFieldProps handlers; edits vanish after blur
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
Correct:
|
|
192
|
-
|
|
193
|
-
```tsx
|
|
194
|
-
muiEditTextFieldProps: ({ cell, row }) => ({
|
|
195
|
-
onBlur: (event) => saveCell(row.id, cell.column.id, event.currentTarget.value),
|
|
196
|
-
}),
|
|
197
|
-
```
|
|
198
|
-
|
|
199
|
-
Edited text lives only in `row._valuesCache` until your code writes it to state or a server and the `data` prop changes.
|
|
200
|
-
|
|
201
|
-
Source: `packages/material-react-table/src/components/inputs/MRT_EditCellTextField.tsx`
|
|
202
|
-
|
|
203
|
-
### MEDIUM Passing removed Material UI text field props to the editor
|
|
204
|
-
|
|
205
|
-
Wrong:
|
|
206
|
-
|
|
207
|
-
```tsx
|
|
208
|
-
muiEditTextFieldProps: { InputProps: { startAdornment: <EuroIcon /> }, inputProps: { maxLength: 40 } }
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
Correct:
|
|
212
|
-
|
|
213
|
-
```tsx
|
|
214
|
-
muiEditTextFieldProps: {
|
|
215
|
-
slotProps: { input: { startAdornment: <EuroIcon /> }, htmlInput: { maxLength: 40 } },
|
|
216
|
-
}
|
|
217
|
-
```
|
|
218
|
-
|
|
219
|
-
Material UI V9 removed `InputProps` and `inputProps` from `TextField`; MRT merges `slotProps.input`, `slotProps.htmlInput`, and `slotProps.select` with its own.
|
|
220
|
-
|
|
221
|
-
Source: `MIGRATION.md`
|
|
222
|
-
|
|
223
|
-
### MEDIUM Editing without a stable row id
|
|
224
|
-
|
|
225
|
-
Wrong:
|
|
226
|
-
|
|
227
|
-
```tsx
|
|
228
|
-
useMaterialReactTable({ columns, data, enableEditing: true })
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
Correct:
|
|
232
|
-
|
|
233
|
-
```tsx
|
|
234
|
-
useMaterialReactTable({ columns, data, enableEditing: true, getRowId: (row) => row.id })
|
|
235
|
-
```
|
|
236
|
-
|
|
237
|
-
Without `getRowId` rows are keyed by index, so `editingRow` and `creatingRow` can point at a different record after sorting, filtering, or an optimistic insert.
|
|
238
|
-
|
|
239
|
-
Source: `docs/examples/editing-crud-modal`
|
|
240
|
-
|
|
241
|
-
## API Discovery
|
|
242
|
-
|
|
243
|
-
Search `node_modules/@lminii/material-react-table/dist/index.d.ts` for `editDisplayMode`, `onEditingRowSave`, `onCreatingRowSave`, `_valuesCache`, and `editInputRefs` to see the exact signatures. The Editing guide at `/docs/guides/editing` lists the related table, column, and state options, and `/docs/examples/editing-crud`, `editing-crud-row`, `editing-crud-cell`, `editing-crud-table`, and `editing-crud-tree` are complete TanStack Query CRUD examples.
|
|
1
|
+
---
|
|
2
|
+
name: editing
|
|
3
|
+
description: >
|
|
4
|
+
Add create, update, and inline editing to Material React Table V4 with enableEditing, editDisplayMode (modal, row, cell, table, custom), createDisplayMode, onEditingRowSave and onCreatingRowSave with exitEditingMode, table.setEditingRow, table.setCreatingRow, muiEditTextFieldProps validation, editVariant select, and the Edit column slot. Load for CRUD tables, editable cells, row forms in a dialog, or when saved values never reach the callback.
|
|
5
|
+
metadata:
|
|
6
|
+
type: framework
|
|
7
|
+
library: '@lminii/material-react-table'
|
|
8
|
+
library_version: '4.0.0'
|
|
9
|
+
framework: react
|
|
10
|
+
requires:
|
|
11
|
+
- getting-started
|
|
12
|
+
- customization
|
|
13
|
+
sources:
|
|
14
|
+
- 'lminii/material-react-table:apps/material-react-table-docs/pages/docs/guides/editing.mdx'
|
|
15
|
+
- 'lminii/material-react-table:apps/material-react-table-docs/examples/editing-crud-modal/sandbox/src/TS.tsx'
|
|
16
|
+
- 'lminii/material-react-table:apps/material-react-table-docs/examples/editing-crud-cell/sandbox/src/TS.tsx'
|
|
17
|
+
- 'lminii/material-react-table:packages/material-react-table/src/components/inputs/MRT_EditCellTextField.tsx'
|
|
18
|
+
- 'lminii/material-react-table:packages/material-react-table/src/types.ts'
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
This skill builds on `getting-started` and `customization`. MRT renders the editing inputs and tracks which row or cell is being edited; persisting the values is always application code, wired through the save callbacks or the text field events.
|
|
22
|
+
|
|
23
|
+
## Setup
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
const table = useMaterialReactTable({
|
|
27
|
+
columns,
|
|
28
|
+
data,
|
|
29
|
+
enableEditing: true,
|
|
30
|
+
editDisplayMode: 'modal', // default; also 'row' | 'cell' | 'table' | 'custom'
|
|
31
|
+
createDisplayMode: 'modal', // default; also 'row' | 'custom'
|
|
32
|
+
getRowId: (row) => row.id,
|
|
33
|
+
onEditingRowSave: async ({ values, table }) => {
|
|
34
|
+
await updateUser(values)
|
|
35
|
+
table.setEditingRow(null) // exit editing mode
|
|
36
|
+
},
|
|
37
|
+
onCreatingRowSave: async ({ values, table }) => {
|
|
38
|
+
await createUser(values)
|
|
39
|
+
table.setCreatingRow(null) // exit creating mode
|
|
40
|
+
},
|
|
41
|
+
renderRowActions: ({ row, table }) => (
|
|
42
|
+
<IconButton onClick={() => table.setEditingRow(row)}><EditIcon /></IconButton>
|
|
43
|
+
),
|
|
44
|
+
renderTopToolbarCustomActions: ({ table }) => (
|
|
45
|
+
<Button onClick={() => table.setCreatingRow(true)}>Create</Button>
|
|
46
|
+
),
|
|
47
|
+
})
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
`enableEditing` accepts a boolean or `(row) => boolean`, on the table and on each column. Column-level `enableEditing: false` renders a disabled field in the modal and the plain cell value in the other modes. The `editingRow`, `creatingRow`, and `editingCell` state slices hold the active row or cell; `table.setEditingRow`, `table.setCreatingRow`, and `table.setEditingCell` change them.
|
|
51
|
+
|
|
52
|
+
## Core Patterns
|
|
53
|
+
|
|
54
|
+
### Modal and row modes save through onEditingRowSave
|
|
55
|
+
|
|
56
|
+
```tsx
|
|
57
|
+
const handleSave: MRT_TableOptions<User>['onEditingRowSave'] = async ({ values, row, table, exitEditingMode }) => {
|
|
58
|
+
const errors = validateUser(values)
|
|
59
|
+
if (Object.values(errors).some(Boolean)) {
|
|
60
|
+
setValidationErrors(errors)
|
|
61
|
+
return // stay in editing mode
|
|
62
|
+
}
|
|
63
|
+
setValidationErrors({})
|
|
64
|
+
await updateUser({ ...row.original, ...values })
|
|
65
|
+
exitEditingMode() // same as table.setEditingRow(null)
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
`values` is a record keyed by column id, holding the edited text of every editable column. Nothing is written to `data`; the callback owns persistence. The callback may return a promise, and the `isSaving` state slice disables the save button and shows a spinner while it is true. `onEditingRowCancel` and `onCreatingRowCancel` fire when the user closes without saving, which is where validation errors get cleared.
|
|
70
|
+
|
|
71
|
+
### Cell and table modes save through the text field events
|
|
72
|
+
|
|
73
|
+
```tsx
|
|
74
|
+
const columns: MRT_ColumnDef<User>[] = [
|
|
75
|
+
{
|
|
76
|
+
accessorKey: 'email',
|
|
77
|
+
header: 'Email',
|
|
78
|
+
muiEditTextFieldProps: ({ cell, row }) => ({
|
|
79
|
+
type: 'email',
|
|
80
|
+
required: true,
|
|
81
|
+
error: !!validationErrors[cell.id],
|
|
82
|
+
helperText: validationErrors[cell.id],
|
|
83
|
+
onBlur: (event) => {
|
|
84
|
+
const value = event.currentTarget.value
|
|
85
|
+
setValidationErrors((prev) => ({ ...prev, [cell.id]: validateEmail(value) ? undefined : 'Invalid email' }))
|
|
86
|
+
setEditedUsers((prev) => ({ ...prev, [row.id]: { ...row.original, email: value } }))
|
|
87
|
+
},
|
|
88
|
+
}),
|
|
89
|
+
},
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
const table = useMaterialReactTable({
|
|
93
|
+
columns,
|
|
94
|
+
data,
|
|
95
|
+
enableEditing: true,
|
|
96
|
+
editDisplayMode: 'cell', // double-click a cell to edit it
|
|
97
|
+
})
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
In `'cell'` mode a double-click opens the field for that cell; in `'table'` mode every editable cell is a field at once. `onEditingRowSave` never fires in these modes. MRT calls your `onBlur` first, then stores the value in `row._valuesCache` and clears `editingCell`, so read `event.currentTarget.value` rather than `cell.getValue()`. Enter blurs the field. For single-click editing set `muiTableBodyCellProps` with an `onClick` that calls `table.setEditingCell(cell)` and focuses `table.refs.editInputRefs.current?.[column.id]`.
|
|
101
|
+
|
|
102
|
+
### Select inputs and custom Edit components
|
|
103
|
+
|
|
104
|
+
```tsx
|
|
105
|
+
{
|
|
106
|
+
accessorKey: 'state',
|
|
107
|
+
header: 'State',
|
|
108
|
+
editVariant: 'select',
|
|
109
|
+
editSelectOptions: usStates, // string[] or { label, value }[]
|
|
110
|
+
muiEditTextFieldProps: { select: true, required: true },
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
accessorKey: 'birthday',
|
|
114
|
+
header: 'Birthday',
|
|
115
|
+
Edit: ({ cell, column, row, table }) => (
|
|
116
|
+
<DatePicker
|
|
117
|
+
value={dayjs(cell.getValue<string>())}
|
|
118
|
+
onChange={(date) => {
|
|
119
|
+
row._valuesCache[column.id] = date?.toISOString()
|
|
120
|
+
if (table.getState().creatingRow?.id === row.id) table.setCreatingRow(row)
|
|
121
|
+
else table.setEditingRow(row)
|
|
122
|
+
}}
|
|
123
|
+
/>
|
|
124
|
+
),
|
|
125
|
+
},
|
|
126
|
+
```
|
|
127
|
+
|
|
128
|
+
`editSelectOptions` also accepts a callback receiving `cell`, `column`, `row`, and `table`. Select values save on change; text values save on blur. A custom `Edit` slot replaces the text field entirely, so it must write to `row._valuesCache[column.id]` and re-set the editing or creating row, otherwise the value never reaches `values` in the save callback.
|
|
129
|
+
|
|
130
|
+
### Customize the dialog and the create row
|
|
131
|
+
|
|
132
|
+
```tsx
|
|
133
|
+
import { MRT_EditActionButtons, createRow } from '@lminii/material-react-table'
|
|
134
|
+
|
|
135
|
+
const table = useMaterialReactTable({
|
|
136
|
+
columns,
|
|
137
|
+
data,
|
|
138
|
+
enableEditing: true,
|
|
139
|
+
positionCreatingRow: 'bottom', // 'top' (default), 'bottom', or a row index
|
|
140
|
+
renderEditRowDialogContent: ({ internalEditComponents, row, table }) => (
|
|
141
|
+
<>
|
|
142
|
+
<DialogTitle>Edit user</DialogTitle>
|
|
143
|
+
<DialogContent sx={{ display: 'flex', flexDirection: 'column', gap: 2 }}>{internalEditComponents}</DialogContent>
|
|
144
|
+
<DialogActions><MRT_EditActionButtons table={table} row={row} variant="text" /></DialogActions>
|
|
145
|
+
</>
|
|
146
|
+
),
|
|
147
|
+
renderTopToolbarCustomActions: ({ table }) => (
|
|
148
|
+
<Button onClick={() => table.setCreatingRow(createRow(table, { id: crypto.randomUUID(), role: 'viewer' }))}>
|
|
149
|
+
Create with defaults
|
|
150
|
+
</Button>
|
|
151
|
+
),
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
`internalEditComponents` is the array of generated fields, one per column, so custom dialog content can reorder them or mix in other inputs. `renderCreateRowDialogContent` is the create counterpart. `table.setCreatingRow(true)` opens a blank row; `createRow(table, defaults)` seeds it. `muiEditRowDialogProps` reaches the Material UI `Dialog` itself. `editDisplayMode: 'custom'` and `createDisplayMode: 'custom'` keep the state slices and callbacks but render no MRT editing UI, for forms in a sidebar.
|
|
156
|
+
|
|
157
|
+
## Common Mistakes
|
|
158
|
+
|
|
159
|
+
### HIGH Forgetting to exit editing mode after saving
|
|
160
|
+
|
|
161
|
+
Wrong:
|
|
162
|
+
|
|
163
|
+
```tsx
|
|
164
|
+
onEditingRowSave: async ({ values }) => {
|
|
165
|
+
await updateUser(values)
|
|
166
|
+
}
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Correct:
|
|
170
|
+
|
|
171
|
+
```tsx
|
|
172
|
+
onEditingRowSave: async ({ values, table }) => {
|
|
173
|
+
await updateUser(values)
|
|
174
|
+
table.setEditingRow(null)
|
|
175
|
+
}
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
MRT does not close the dialog or row on its own, so validation can keep it open. Call `exitEditingMode()` or `table.setEditingRow(null)` once the save succeeds, and the create counterpart `table.setCreatingRow(null)`.
|
|
179
|
+
|
|
180
|
+
Source: `docs/guides/editing.mdx`
|
|
181
|
+
|
|
182
|
+
### HIGH Expecting the data array to update itself
|
|
183
|
+
|
|
184
|
+
Wrong:
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
editDisplayMode: 'cell',
|
|
188
|
+
// no muiEditTextFieldProps handlers; edits vanish after blur
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
Correct:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
muiEditTextFieldProps: ({ cell, row }) => ({
|
|
195
|
+
onBlur: (event) => saveCell(row.id, cell.column.id, event.currentTarget.value),
|
|
196
|
+
}),
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Edited text lives only in `row._valuesCache` until your code writes it to state or a server and the `data` prop changes.
|
|
200
|
+
|
|
201
|
+
Source: `packages/material-react-table/src/components/inputs/MRT_EditCellTextField.tsx`
|
|
202
|
+
|
|
203
|
+
### MEDIUM Passing removed Material UI text field props to the editor
|
|
204
|
+
|
|
205
|
+
Wrong:
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
muiEditTextFieldProps: { InputProps: { startAdornment: <EuroIcon /> }, inputProps: { maxLength: 40 } }
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
Correct:
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
muiEditTextFieldProps: {
|
|
215
|
+
slotProps: { input: { startAdornment: <EuroIcon /> }, htmlInput: { maxLength: 40 } },
|
|
216
|
+
}
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Material UI V9 removed `InputProps` and `inputProps` from `TextField`; MRT merges `slotProps.input`, `slotProps.htmlInput`, and `slotProps.select` with its own.
|
|
220
|
+
|
|
221
|
+
Source: `MIGRATION.md`
|
|
222
|
+
|
|
223
|
+
### MEDIUM Editing without a stable row id
|
|
224
|
+
|
|
225
|
+
Wrong:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
useMaterialReactTable({ columns, data, enableEditing: true })
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
Correct:
|
|
232
|
+
|
|
233
|
+
```tsx
|
|
234
|
+
useMaterialReactTable({ columns, data, enableEditing: true, getRowId: (row) => row.id })
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
Without `getRowId` rows are keyed by index, so `editingRow` and `creatingRow` can point at a different record after sorting, filtering, or an optimistic insert.
|
|
238
|
+
|
|
239
|
+
Source: `docs/examples/editing-crud-modal`
|
|
240
|
+
|
|
241
|
+
## API Discovery
|
|
242
|
+
|
|
243
|
+
Search `node_modules/@lminii/material-react-table/dist/index.d.ts` for `editDisplayMode`, `onEditingRowSave`, `onCreatingRowSave`, `_valuesCache`, and `editInputRefs` to see the exact signatures. The Editing guide at `/docs/guides/editing` lists the related table, column, and state options, and `/docs/examples/editing-crud`, `editing-crud-row`, `editing-crud-cell`, `editing-crud-table`, and `editing-crud-tree` are complete TanStack Query CRUD examples.
|