1771 Technologies Logo

Cells

Cell Editing

To make a column editable in Graphite Grid, set the editable property to true on the column definition.

When a column is editable, its contents can be edited. Cell editing must be activated to begin. The cellEditPointerActivator determines how cell editing can be activated via a pointer event. The Enter key will also activate cell editing when the cell is focused.

By default, Graphite Grid displays an <input /> to edit the cell. The default component can be changed using the editableCellRenderer property on the column definition.

A cell edit operation happens in steps:

  1. Cell editing must be activated first.
  2. The cell's value is edited.
  3. The value is accepted (either by pressing the Enter key or blurring the cell).
  4. The onCellEdit callback on the column definition is called.

An edit operation can be aborted by pressing the Escape key.

Cell Edit Pointer Activator

By default, double-clicking an editable cell begins the cell edit operation. This can be changed using the cellEditPointerActivator on the grid state. It may be set to:

  • "single-click": A single click on a cell begins the cell edit
  • "double-click": A double click is required to begin the cell edit; once started, a single click on another cell begins editing the clicked cell
  • "none": Cell editing cannot be activated by clicking cells

Updating Row Data With Cell Editing

Graphite Grid never changes cell values. Any updates must be handled through an onCellEdit callback or another application event. The grid considers all data provided to it immutable.

In the example below, every column is made editable by providing the editable logic to the baseColumnDefinition. Add the properties directly to the column definition to make only specific columns editable.

// Our original data before any edits
const originalData = [
  ["apple", "banana", "cherry", "date"],
  ["elephant", "frog", "giraffe", "hippo"],
  // ...
];
 
// A function to handle cell edits
function handleEdit({ api, column, row, value }: OnCellEditParams<string[]>) {
  if (typeof column.field !== "number" || row.kind === "branch") {
    return;
  }
  const source = api.getRowDataSource();
  if (source?.kind !== "client") return;
 
  source.data[row.editIndex][column.field] = value as string;
 
  api.refreshRowDataSource();
}
 
export function CellEditing() {
  const grid = useGraphiteGrid<string[]>({
    initial: {
      // Define our columns
      columnDefinitions: [
        { id: "Alpha", field: 0 },
        { id: "Beta", field: 1 },
        { id: "Stock Price", field: 2 },
        { id: "Gamma", field: 3 },
      ],
      baseColumnDefinition: {
        editable: true,
        onCellEdit: handleEdit,
        cellTheme: ({ column, row }) => {
          if (typeof column.field !== "number" || row.kind === "branch") {
            return {};
          }
 
          // our value has been updated
          if (row.data[column.field] !== originalData[row.editIndex][column.field]) {
            return {
              backgroundColor: "#f6d084",
              keyedThemes: {
                dark: {
                  backgroundColor: "#d35801dc",
                },
              },
            };
          }
          return {};
        },
      },
      rowDataSource: {
        kind: "client",
        data: structuredClone(originalData),
      },
    },
  });
 
  return (
    <div style={{ height: 400 }}>
      <GraphiteGridDom state={grid} />
    </div>
  );
}

Providing A EditCellRenderer

The example below shows how a custom editable cell renderer can be used. When providing a column with an editableCellRenderer, two properties, value and onChange, will be present on the props provided to the renderer. For normal grid edit functionality to work as expected, your custom component should call onChange whenever the value should be changed. The value property will be the current value after any cell edits. When the cell edit ends, this will be provided to the onCellEdit callback.

export function CellEditorCustom() {
  const grid = useGraphiteGrid<string[]>({
    initial: {
      columnDefinitions: [
        {
          id: "Alpha",
          field: 0,
          editableCellRenderer({ onChange, value }) {
            return (
              <input
                type="date"
                value={value as string}
                onChange={(e) => onChange(e.target.value)}
              />
            );
          },
        },
        // other columns
      ],
      // other props
    },
  });
 
  // ...
}

By setting the editable property on column definitions, handling updates through the onCellEdit callback, and optionally providing a custom editableCellRenderer, you can enable cell editing in Graphite Grid to suit your application's needs.