Skip to main content

Editing & Clipboard

OGrid supports inline cell editing, clipboard copy/paste, drag-to-fill, and undo/redo -- all working together through onCellValueChanged and valueParser.

Live Demo

Double-click any cell to edit, or press F2
Live
Name
Department
Status
Salary
Alice Johnson
Engineering
Active
$50,000
Bob Smith
Marketing
Draft
$53,500
Carol Lee
Sales
Archived
$57,000
David Kim
Finance
Active
$60,500
Eve Torres
Operations
Draft
$64,000
Frank Wu
Engineering
Archived
$67,500
Grace Park
Marketing
Active
$71,000
Henry Adams
Sales
Draft
$74,500
Irene Costa
Finance
Archived
$78,000
Jack Rivera
Operations
Active
$81,500
Try it in your framework

The demo above uses Radix UI for styling. To see this feature with your framework's design system (Fluent UI, Material UI, Vuetify, PrimeNG, etc.), click "Open in online demo" below the demo.

Quick Example

import { OGrid, useUndoRedo } from '@alaarab/ogrid-react-radix';
import { useState } from 'react';

const DEPTS = ['Engineering', 'Marketing', 'Sales', 'Finance', 'Operations'];
const STATUSES = ['Active', 'Draft', 'Archived'];

const columns = [
{ columnId: 'name', name: 'Name', editable: true },
{
columnId: 'department',
name: 'Department',
editable: true,
cellEditor: 'richSelect',
cellEditorParams: { values: DEPTS },
},
{
columnId: 'status',
name: 'Status',
editable: true,
cellEditor: 'select',
cellEditorParams: { values: STATUSES },
},
{
columnId: 'salary',
name: 'Salary',
editable: true,
type: 'numeric',
valueParser: ({ newValue }) => {
const num = Number(newValue);
return isNaN(num) || num < 0 ? undefined : num; // reject invalid
},
valueFormatter: (v) => `$${Number(v).toLocaleString()}`,
},
];

function App() {
const [data, setData] = useState(initialData);
const { handleCellValueChanged, undo, redo, canUndo, canRedo } = useUndoRedo({
data, setData, getRowId: (item) => item.id,
});

return (
<OGrid
columns={columns}
data={data}
getRowId={(item) => item.id}
editable
onCellValueChanged={handleCellValueChanged}
onUndo={undo}
onRedo={redo}
canUndo={canUndo}
canRedo={canRedo}
/>
);
}
Switching UI libraries

The OGrid component has the same props across all React UI packages. To switch, just change the import:

  • Radix (lightweight, default): from '@alaarab/ogrid-react-radix'
  • Fluent UI (Microsoft 365 / SPFx): from '@alaarab/ogrid-react-fluent' — wrap in <FluentProvider>
  • Material UI (MUI v7): from '@alaarab/ogrid-react-material' — wrap in <ThemeProvider>

This single setup gives you inline editing, clipboard paste, fill handle, and full undo/redo.

Inline Editing

Double-click or press F2 to edit. Enter commits and moves down, Tab commits and moves right, Escape cancels.

Built-in Editors

cellEditorDescription
'text' (default)Standard text input
'select'Dropdown from cellEditorParams.values
'checkbox'Toggle boolean
'richSelect'Searchable dropdown with keyboard nav

Rich Select

{
columnId: 'category',
editable: true,
cellEditor: 'richSelect',
cellEditorParams: {
values: ['Engineering', 'Design', 'Marketing', 'Sales'],
formatValue: (v) => `Dept: ${v}`,
},
}

Per-Row Editability

{ columnId: 'name', editable: (item) => item.status !== 'locked' }

Custom Editor

Pass a component to cellEditor. Use cellEditorPopup: true for a popover:

function DateEditor({ value, onValueChange, onCommit, onCancel }: ICellEditorProps<Task>) {
return (
<input
type="date"
value={value as string}
onChange={(e) => onValueChange(e.target.value)}
onKeyDown={(e) => {
if (e.key === 'Enter') onCommit();
if (e.key === 'Escape') onCancel();
}}
autoFocus
/>
);
}

// In column def:
{ columnId: 'dueDate', editable: true, cellEditor: DateEditor, cellEditorPopup: true }

Value Parsing

valueParser validates input for editing, paste, fill, and delete. Return undefined to reject:

{ columnId: 'age', editable: true, type: 'numeric',
valueParser: ({ newValue }) => {
const num = Number(newValue);
return isNaN(num) || num < 0 || num > 150 ? undefined : num;
},
}

Clipboard

Select cells, then Ctrl+C to copy, Ctrl+V to paste
Live
Name
Department
Status
Salary
Alice Johnson
Engineering
Active
$50,000
Bob Smith
Marketing
Draft
$53,500
Carol Lee
Sales
Archived
$57,000
David Kim
Finance
Active
$60,500
Eve Torres
Operations
Draft
$64,000
Frank Wu
Engineering
Archived
$67,500
Grace Park
Marketing
Active
$71,000
Henry Adams
Sales
Draft
$74,500
Irene Costa
Finance
Archived
$78,000
Jack Rivera
Operations
Active
$81,500

Standard keyboard shortcuts on selected cells:

KeyActionRequires editable
Ctrl+C (Cmd+C)Copy as tab-delimited textNo
Ctrl+V (Cmd+V)Paste into cellsYes
Ctrl+X (Cmd+X)Cut (copy + clear)Yes
Delete / BackspaceClear selected cellsYes
  • Copy uses valueFormatter so copied values match the display.
  • Paste calls valueParser on each value and fires onCellValueChanged per cell.

Fill Handle

Select a cell, then drag the green square at the bottom-right corner to fill
Live
Name
Department
Status
Salary
Alice Johnson
Engineering
Active
$50,000
Bob Smith
Marketing
Draft
$53,500
Carol Lee
Sales
Archived
$57,000
David Kim
Finance
Active
$60,500
Eve Torres
Operations
Draft
$64,000
Frank Wu
Engineering
Archived
$67,500
Grace Park
Marketing
Active
$71,000
Henry Adams
Sales
Draft
$74,500
Irene Costa
Finance
Archived
$78,000
Jack Rivera
Operations
Active
$81,500

A small square at the bottom-right of the selection. Drag it down to fill cells with the source value (like Excel).

  • Requires editable={true} and cellSelection={true} (default).
  • Calls valueParser per cell -- return undefined to skip.
  • Each filled cell fires onCellValueChanged.
  • Uses requestAnimationFrame for smooth drag performance.

Undo / Redo

The useUndoRedo hook tracks edit history (including paste, fill, and delete). See the quick example above.

Hook InputTypeDescription
dataT[]Current data array
setData(data: T[]) => voidState setter
getRowId(item: T) => RowIdRow identifier
Hook OutputTypeDescription
handleCellValueChanged(event) => voidWraps edits onto the undo stack
undo / redo() => voidRevert / re-apply
canUndo / canRedobooleanStack status

Shortcuts: Ctrl+Z (undo), Ctrl+Y (redo). Also available in the right-click context menu.

Props Summary

PropTypeDescription
editablebooleanEnable editing grid-wide (on OGrid)
editableboolean | (item: T) => booleanPer-column/row (on IColumnDef)
cellEditor'text' | 'select' | 'checkbox' | 'richSelect' | ComponentTypeEditor type
cellEditorPopupbooleanRender custom editor in a popover
cellEditorParamsCellEditorParamsEditor parameters (e.g., { values: [...] })
valueParser(params) => unknownValidate on edit/paste/fill/delete. Return undefined to reject.
valueFormatter(value, item) => stringFormat display & copy output
onCellValueChanged(event) => voidFired after any cell value change
onUndo / onRedo() => voidUndo/redo callbacks
canUndo / canRedobooleanEnable/disable undo/redo in context menu