Skip to content

EditingPlugin

Editing Plugin for tbw-grid

Enables inline cell editing in the grid. Provides built-in editors for common data types and supports custom editor functions for specialized input scenarios.

Editing is delivered as a plugin rather than built into the core grid:

  • Smaller bundle — Apps that only display data don’t pay for editing code
  • Clear intent — Explicit plugin registration makes editing capability obvious
  • Runtime validation — Using editable: true without the plugin throws a helpful error
import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';

Configure how editing is triggered with the editOn option:

ValueBehavior
'click'Single click enters edit mode (default)
'dblclick'Double-click enters edit mode
KeyAction
EnterCommit edit and move down
TabCommit edit and move right
EscapeCancel edit, restore original value
Arrow KeysNavigate between cells (when not editing)
grid.gridConfig = {
columns: [
{ field: 'name', editable: true },
{ field: 'price', type: 'number', editable: true },
{ field: 'active', type: 'boolean', editable: true },
],
plugins: [new EditingPlugin({ editOn: 'dblclick' })],
};
grid.on('cell-commit', ({ field, oldValue, newValue }) => {
console.log(`${field}: ${oldValue}${newValue}`);
});
columns: [
{
field: 'status',
editable: true,
editor: (ctx) => {
const select = document.createElement('select');
['pending', 'active', 'completed'].forEach(opt => {
const option = document.createElement('option');
option.value = opt;
option.textContent = opt;
option.selected = ctx.value === opt;
select.appendChild(option);
});
select.addEventListener('change', () => ctx.commit(select.value));
return select;
},
},
]

Extends BaseGridPlugin

Inherited methods like attach(), detach(), afterRender(), etc. are documented in the base class.

EventDescriptionTriggered By
changed-rows-resetEmitted when tracking is reset (unless silent)resetChangedRows()
cell-commitEmitted when the cell value is committed (on blur or Enter)beginCellEdit(), beginBulkEdit()
row-commitEmitted after the row edit is committedbeginBulkEdit(), commitActiveRowEdit()

Get all rows that have been modified. Uses ID-based lookup for stability when rows are reordered.

readonly changedRows: T[]

Get IDs of all modified rows.

readonly changedRowIds: string[]

Get the currently active edit row index, or -1 if not editing.

readonly activeEditRow: number

Get the currently active edit column index, or -1 if not editing.

readonly activeEditCol: number

Whether any row in the grid is dirty.

readonly dirty: boolean

Whether all rows are pristine.

readonly pristine: boolean

Get IDs of all dirty rows.

readonly dirtyRowIds: string[]

Check if a specific row is currently being edited.

isRowEditing(rowIndex: number): boolean
NameTypeDescription
rowIndexnumber

Check if a specific cell is currently being edited.

isCellEditing(rowIndex: number, colIndex: number): boolean
NameTypeDescription
rowIndexnumber
colIndexnumber

Check if a specific row has been modified.

isRowChanged(rowIndex: number): boolean
NameTypeDescription
rowIndexnumberRow index to check (will be converted to ID internally)

Check if a row with the given ID has been modified.

isRowChangedById(rowId: string): boolean
NameTypeDescription
rowIdstringRow ID to check

Check if a row differs from its baseline. Requires dirtyTracking: true.

isDirty(rowId: string): boolean
NameTypeDescription
rowIdstring

Inverse of isDirty.

isPristine(rowId: string): boolean
NameTypeDescription
rowIdstring

Re-snapshot baseline from current data (call after a successful save).

markAsPristine(rowId: string): void
NameTypeDescription
rowIdstring

Mark a row as new (auto-called by insertRow() when dirty tracking is on).

markAsNew(rowId: string): void
NameTypeDescription
rowIdstring

Mark a row as dirty after an external mutation that bypassed the editing pipeline.

markAsDirty(rowId: string): void
NameTypeDescription
rowIdstring

Mark all tracked rows as pristine (call after a batch save).

markAllPristine(): void

Get a deep clone of the original (baseline) row data. Returns undefined for new rows.

getOriginalRow(rowId: string): T | undefined
NameTypeDescription
rowIdstring

Lightweight check for whether a baseline exists (no cloning).

hasBaseline(rowId: string): boolean
NameTypeDescription
rowIdstring

Get all dirty rows with their original and current data.

getDirtyRows(): DirtyRowEntry<T>[]

Revert a row to its baseline values (mutates the current row in-place). Triggers a re-render.

revertRow(rowId: string): void
NameTypeDescription
rowIdstringRow ID (from getRowId)

Revert all dirty rows to their baseline values and re-render.

revertAll(): void

Mark a cell as invalid with an optional validation message. Invalid cells are marked with a data-invalid attribute for styling.

setInvalid(rowId: string, field: string, message: string): void
NameTypeDescription
rowIdstringThe row ID (from getRowId)
fieldstringThe field name
messagestringOptional validation message (for tooltips or display)
// In cell-commit handler:
grid.on('cell-commit', (detail, e) => {
if (detail.field === 'email' && !isValidEmail(detail.value)) {
detail.setInvalid('Invalid email format');
}
});
// Or programmatically:
editingPlugin.setInvalid('row-123', 'email', 'Invalid email format');

Clear the invalid state for a specific cell.

clearInvalid(rowId: string, field: string): void
NameTypeDescription
rowIdstring
fieldstring

Clear all invalid cells for a specific row.

clearRowInvalid(rowId: string): void
NameTypeDescription
rowIdstring

Clear all invalid cell states across all rows.

clearAllInvalid(): void

Check if a specific cell is marked as invalid.

isCellInvalid(rowId: string, field: string): boolean
NameTypeDescription
rowIdstring
fieldstring

Get the validation message for an invalid cell.

getInvalidMessage(rowId: string, field: string): string | undefined
NameTypeDescription
rowIdstring
fieldstring

Check if a row has any invalid cells.

hasInvalidCells(rowId: string): boolean
NameTypeDescription
rowIdstring

Get all invalid fields for a row.

getInvalidFields(rowId: string): Map<string, string>
NameTypeDescription
rowIdstring

Reset all change tracking.

resetChangedRows(silent: boolean): void
NameTypeDescription
silentbooleanIf true, suppresses the changed-rows-reset event
EventDescription
changed-rows-resetEmitted when tracking is reset (unless silent)

Programmatically begin editing a cell.

beginCellEdit(rowIndex: number, field: string): void
NameTypeDescription
rowIndexnumberIndex of the row to edit
fieldstringField name of the column to edit
EventDescription
cell-commitEmitted when the cell value is committed (on blur or Enter)

Programmatically begin editing all editable cells in a row.

beginBulkEdit(rowIndex: number): void
NameTypeDescription
rowIndexnumberIndex of the row to edit
EventDescription
cell-commitEmitted for each cell value that is committed
row-commitEmitted when focus leaves the row

Commit the currently active row edit.

commitActiveRowEdit(): void
EventDescription
row-commitEmitted after the row edit is committed

Cancel the currently active row edit.

cancelActiveRowEdit(): void

AI assistants: For complete API documentation, implementation guides, and code examples for this library, see https://raw.githubusercontent.com/OysteinAmundsen/toolbox/main/llms-full.txt