Row Editing
Open every editable cell in a row at once and commit them as one change — one write for your API, one entry in the undo history, and one validation verdict for the whole row.
Edit a whole row
Double-click any cell: the row opens. Enter commits it, Escape discards it, Tab wraps inside it — and one Ctrl+Z takes the whole row back.
One gesture, one change
Double-click any cell: every editable cell in that row opens at once, and the row is banded so you can see what you are about to save. Enter from any of them writes the whole row, Escape discards all of it, and Tab moves between the row's own cells and wraps at the end — it never leaves you with half a row open.
One undo, not five
Change the guest and the rate, press Enter, then press Ctrl+Z once: both cells go back. A row is one entry in the history, because it was one decision.
Validation is all-or-nothing
Nights accepts 1–30 and Guest is required. Put 99 in Nights, change the guest too, and press Enter: nothing is written, the row stays open, and the failing cell shows why. A half-written row is the surprise this mode exists to avoid — fix the cell and press Enter again.
Driven from your own buttons
Sort the grid first, then press Edit next unpaid — it still opens the booking it meant, because the API takes the row's id and not its position.
Editing from your own button — by identity
Sort the grid first, then press Edit next unpaid. It still opens the
booking it meant, because startEditing() takes the row's id — the same key selection
and keyboard focus use — not its position on screen.
grid.startEditing(booking.id); // the whole row
grid.startEditing(booking.id, 'rate'); // just one cell, even in fullRow mode
Save and Cancel are your buttons
stopEditing(true) commits — atomically, so a refused row stays open with its message —
and stopEditing(false) discards. Both return whether anything was open, and
editingRowId() is a signal, so a Save button can be disabled from real state instead
of a guess.
When to use it
Row editing suits records people change as a unit — a booking, an invoice line, a contact. The user opens the row, fixes what needs fixing, and commits once: one write for your API, one entry in the undo history, and one validation verdict for the whole row.
readonly config: GridConfig<Booking> = { editMode: 'fullRow', trackBy: 'id' };
What changes, and what does not
- Your column definitions do not. The same
editable,editorandvalidaterules drive the row's cells. - Your existing events keep firing. A committed row emits
(cellEditCommit)for each changed cell and one(rowEditCommit)summary — switching a grid to row editing never leaves a listener silently dead. - Single-cell editing is still available from the API:
startEditing(rowId, colKey)opens exactly that cell.
Keyboard
- Enter — commit the row (from any of its cells).
- Escape — discard the whole row.
- Tab / Shift+Tab — move between the row's editable cells; wraps at the ends.
- Ctrl+Z — one press takes the committed row back (needs
undoRedo: true).
trackBy is required: sessions, undo entries and the imperative API are all keyed by
row identity, which is what makes them survive sorting, filtering and scrolling.
Row editing options
| Property | Type | Default | Description |
|---|---|---|---|
| config.editMode | 'cell' | 'fullRow' | 'cell' | 'fullRow' opens every editable cell of a row together and commits them as one change. editTrigger still chooses click vs double-click. |
| (rowEditCommit) | RowEditCommit<T> | — | Fires once per committed row, after that row's per-cell (cellEditCommit)s. Carries rowId, changes (only the cells that changed), oldRow and newRow. |
| startEditing(rowId, colKey?) | (rowId, colKey?) => boolean | — | Open an editor by row identity. No colKey: the whole row in fullRow mode, otherwise the first editable cell. Returns false for an unknown row, a group row, or a row with no editable columns. |
| stopEditing(commit?) | (commit?: boolean) => boolean | commit = true | Commit (atomically, for a row) or discard the open session. Returns whether anything was open. A refused commit leaves the session open with its messages. |
| editingRowId() | Signal<unknown | null> | null | The row open as a full-row session — drive your own Save/Cancel buttons from it. |
| editingCell() | Signal<{ rowId, colKey } | null> | null | The single cell being edited. Null while a row session is open. |
| column.validate | ValidationRules | — | Unchanged by this mode, and applied per cell. In the default editValidation: 'block' a single failure refuses the WHOLE row. See Edit Validation. |
| --gc-row-editing-bg / --gc-row-editing-outline | CSS value | blue tint / blue outline | The band on a row being edited. See Theming. |