Inline Editing in Apex Grid
The Apex grid supports inline editing in cell or row mode. Editing is opt-in at the grid level and at the column level: only columns marked editable: true participate.
Enabling editing
grid.editing = {
enabled: true,
mode: 'cell', // 'cell' | 'row'
trigger: 'doubleClick', // 'click' | 'doubleClick'
};
Mark editable columns:
{
key: 'name',
editable: true,
}
Configuration
type EditingConfiguration = {
enabled: boolean;
mode?: 'cell' | 'row';
trigger?: 'click' | 'doubleClick';
history?: { enabled: boolean; stackSize?: number }; // undo/redo, see below
};
In cell mode, exactly one cell is in edit at a time. In row mode, all editable cells in the active row enter edit together; commitEdit() flushes all pending values for the row in one event cycle.
Programmatic API
await grid.editCell(rowIndex, columnKey);
await grid.commitEdit();
await grid.cancelEdit();
const cell = grid.editingCell; // currently-edited cell, if any
const row = grid.editingRow; // currently-edited row in row mode
Keyboard editing
Besides the pointer trigger, the active cell's editor opens from the keyboard with Enter or F2 (new in 3.4.0; editing was previously pointer-only). While editing, Enter or Tab commits (Tab commits and moves), and Escape cancels. Clearing a number or currency editor commits null rather than NaN, so an emptied numeric cell reads as empty instead of an invalid number. See Accessibility for the full key map.
Events
- cellValueChanging: cancellable; fires before a cell's value is committed. Read
event.detail.oldValue/event.detail.newValueto validate. - cellValueChanged: fires after a successful commit.
- cellValidationFailed: fires when a column validator rejects an edit. Detail:
{ key, rowIndex, data, value, errors }. - rowEditStarted: row mode only; fires when the active row enters edit.
- rowEditEnded: row mode only; fires when the active row commits or cancels.
- historyChanged: fires when the undo/redo stack changes (requires
editing.history). Detail:{ canUndo, canRedo }.
Built-in editors
Editor templates come from the column type. Built-in editors for string, number, boolean, select, rating, and date types are provided. Custom column types register their own editor templates against the column-type registry.
Validation
Since v3.3, columns take a declarative validators array. Validators run inside the commit path (before the cancellable cellValueChanging gate); a failure keeps the editor open, marks the cell (aria-invalid plus an inline error-message node), and blocks the commit.
import { required, min, max, pattern, custom } from 'apex-grid';
const columns = [
{ key: 'name', editable: true, validators: [required('Name is required')] },
{ key: 'age', editable: true, type: 'number', validators: [min(18), max(99)] },
{ key: 'email', editable: true, validators: [pattern(/^[^@\s]+@[^@\s]+$/, 'Invalid email')] },
];
Built-ins are required, min, max, pattern, and custom; any (value, ctx) => string | null function works as a validator (return an error string to reject, null to accept). In row mode all pending cells are validated atomically, so there is no partial write. When a validator rejects, the grid fires a cellValidationFailed event:
grid.addEventListener('cellValidationFailed', (event) => {
const { key, rowIndex, value, errors } = event.detail;
console.warn(`${key} @ row ${rowIndex} rejected:`, errors);
});
For a simpler ad-hoc check, you can still listen to cellValueChanging and call event.preventDefault() to reject the new value; the grid keeps the cell in edit and the editor focused so the user can correct the entry.
Undo / redo
Opt in to an edit-history stack with editing.history. Every committed cell edit is recorded (single edits, row-mode commits, and enterprise paste / fill each collapse to one step):
grid.editing = { enabled: true, mode: 'cell', history: { enabled: true } };
grid.undo(); // or Ctrl/Cmd+Z
grid.redo(); // or Ctrl/Cmd+Shift+Z / Ctrl+Y
grid.clearHistory();
grid.canUndo; // boolean getter
grid.canRedo; // boolean getter
Keyboard shortcuts fire while the grid body has focus, so an open editor's native text undo is untouched. The stack holds 100 commands by default; raise it with history: { enabled: true, stackSize: 200 }. A historyChanged event ({ canUndo, canRedo }) fires whenever the stack changes, so you can enable / disable your own undo / redo buttons.