Editing (inline / modal / slideover / in-cell)
The grid supports full CRUD with four presentation modes you can switch between:
- inline — edit the whole row's cells in place, with Save/Cancel.
- modal — a centered dialog form.
- slideover — a right-side flyout form.
- incell — edit a single cell in place (spreadsheet-style); optionally batch multiple edits and save them together.
Editing is server-validated and only writes columns you mark editable.
Server side
Mark columns editable with validation rules (the write allow-list):
Grid::table('sales')->key('id')
->column('status', editable: true, editor: 'select',
rules: 'required|in:pending,paid,shipped,delivered,returned')
->column('qty', type: 'number', editable: true, rules: 'required|integer|min:0')
->column('revenue', type: 'number', editable: true, rules: 'required|numeric');
Expose a mutation endpoint (Vue/Svelte) or let Livewire call it directly:
use Elyra\DataGrid\Protocol\GridMutation;
Route::post('/api/sales/mutate', fn (Request $r) =>
salesGrid()->mutate(GridMutation::fromArray($r->all())));
mutate() returns a GridMutationResult:
{ "ok": true, "id": 42, "row": { "id": 42, "status": "paid", ... } }
{ "ok": false, "errors": { "status": ["The selected status is invalid."] } }
Livewire
class SalesGrid extends DataGrid
{
public bool $editable = true;
public string $editMode = 'slideover'; // 'inline' | 'modal' | 'slideover'
// ... definition() + columns() (with editor/options) + optional aggregates()
}
The grid adds a command column (edit / delete), a New button, and renders
the chosen editor for each editable column. Validation errors appear inline in
the form. Persistence goes straight through GridDefinition::mutate().
Vue / Svelte
Provide an editing option with a mutate function and the mode:
const options = {
/* columns with editable/editor/options ... */
editing: {
mode: 'slideover', // 'inline' | 'modal' | 'slideover'
mutate: async (m) => (await fetch('/api/sales/mutate', {
method: 'POST',
headers: { 'Content-Type': 'application/json', Accept: 'application/json' },
body: JSON.stringify(m),
})).json(),
},
};
Programmatic (client core):
grid.beginEdit(rowId); // edit an existing row
grid.beginCreate(); // new row
grid.setDraft('status', 'paid');
await grid.commitEdit(); // validates + persists via mutate()
grid.cancelEdit();
await grid.removeRow(rowId);
grid.isEditing(rowId);
On success the edited row updates in place; create/delete invalidate the cached total and refetch.
Inline editing
In inline mode, clicking Edit turns the row's editable cells into inputs
(using each column's editor), with Save / Cancel in the command
column. Press Enter to save.
In-cell & batch editing
incell mode is spreadsheet-style: double-click an editable cell to edit it
in place. Press Enter or blur to commit, Escape to cancel.
- Immediate (default): each committed cell persists straight away (one
updatemutation for that field). - Batch (
batch: true): committed cells accumulate as unsaved changes, highlighted in the grid. A toolbar Save (n) / Cancel bar appears; Save persists every dirty row (oneupdatemutation per row) and Cancel discards them.
// Vue / Svelte
editing: { mode: 'incell', batch: true, mutate }
// Livewire
public string $editMode = 'incell';
public bool $batchEdit = true;
Unsaved cells are overlaid on the displayed data and flagged with a dg-cell-dirty
style, so users see pending edits before saving. Client-core exposes the
machinery for custom UIs: commitCell, isDirty, dirtyValueOf, cellValue,
dirtyRowCount, saveBatch, cancelBatch.
Editors
text, number, date, select (uses options), and checkbox. See
Columns.
Clipboard paste
With editing enabled, paste tab-separated data (e.g. from a spreadsheet) starting at the active cell — it maps onto editable columns and persists each affected row. See Selection & keyboard.