# Cell Editing

Grid supports Excel-like cell editing where users click on a cell to edit its value.

```tsx
import { createModel } from "cx/data";
import { Controller } from "cx/ui";
import { Grid, NumberField, TextField, LookupField } from "cx/widgets";

interface Person {
  id: number;
  fullName: string;
  continent: string;
  browser: string;
  visits: number;
}

interface PageModel {
  records: Person[];
  $record: Person;
}

const m = createModel<PageModel>();

class PageController extends Controller {
  onInit() {
    this.store.set(m.records, [
      {
        id: 1,
        fullName: "Alice Johnson",
        continent: "North America",
        browser: "Chrome",
        visits: 45,
      },
      {
        id: 2,
        fullName: "Bob Smith",
        continent: "Europe",
        browser: "Firefox",
        visits: 32,
      },
      {
        id: 3,
        fullName: "Carol White",
        continent: "Asia",
        browser: "Safari",
        visits: 28,
      },
      {
        id: 4,
        fullName: "David Brown",
        continent: "Europe",
        browser: "Edge",
        visits: 51,
      },
      {
        id: 5,
        fullName: "Eva Green",
        continent: "North America",
        browser: "Chrome",
        visits: 19,
      },
      {
        id: 6,
        fullName: "Frank Wilson",
        continent: "Asia",
        browser: "Firefox",
        visits: 37,
      },
      {
        id: 7,
        fullName: "Grace Lee",
        continent: "Europe",
        browser: "Chrome",
        visits: 42,
      },
      {
        id: 8,
        fullName: "Henry Taylor",
        continent: "North America",
        browser: "Safari",
        visits: 25,
      },
    ]);
  }
}

const continentOptions = [
  { id: "Africa", text: "Africa" },
  { id: "Asia", text: "Asia" },
  { id: "Europe", text: "Europe" },
  { id: "North America", text: "North America" },
  { id: "South America", text: "South America" },
];

const browserOptions = [
  { id: "Chrome", text: "Chrome" },
  { id: "Firefox", text: "Firefox" },
  { id: "Safari", text: "Safari" },
  { id: "Edge", text: "Edge" },
];

export default (
  <Grid
    controller={PageController}
    records={m.records}
    style="height: 400px"
    scrollable
    cellEditable
    lockColumnWidths
    onCellEdited={(change, record) => {
      console.log("Cell edited:", change, record);
    }}
    columns={[
      {
        header: "Name",
        field: "fullName",
        editor: <TextField value={m.$record.fullName} required visited />,
      },
      {
        header: "Continent",
        field: "continent",
        editor: (
          <LookupField
            value={m.$record.continent}
            options={continentOptions}
            required
            autoOpen
            submitOnEnterKey
          />
        ),
      },
      {
        header: "Browser",
        field: "browser",
        editor: (
          <LookupField
            value={m.$record.browser}
            options={browserOptions}
            required
            autoOpen
            submitOnEnterKey
          />
        ),
      },
      {
        header: "Visits",
        field: "visits",
        align: "right",
        editor: (
          <NumberField
            value={m.$record.visits}
            required
            visited
            inputStyle="text-align: right"
          />
        ),
      },
    ]}
    recordAlias={m.$record}
  />
);

```

Click on any cell to edit it. Press Enter to confirm or Escape to cancel.

## Enabling Cell Editing

Set the `cellEditable` flag on the Grid and specify `editor` configurations for editable columns:

```tsx
<Grid
  cellEditable
  lockColumnWidths
  onCellEdited={(change, record) => {
    console.log("Cell edited:", change, record);
  }}
  columns={[
    {
      header: "Name",
      field: "fullName",
      editor: <TextField value={m.$record.fullName} required />,
    },
    {
      header: "Browser",
      field: "browser",
      editor: <LookupField value={m.$record.browser} options={browserOptions} autoOpen />,
    },
  ]}
/>
```

## Editor Configuration

The `editor` property accepts any widget configuration. Common editors include:

- `TextField` for text input
- `NumberField` for numeric values
- `LookupField` for dropdown selection (use `autoOpen` and `submitOnEnterKey` for better UX)
- `Select` for simple option lists

## onCellEdited Callback

The `onCellEdited` callback is triggered when a cell value changes:

```tsx
onCellEdited={(change, record) => {
  // change contains: { field, oldValue, newValue }
  // record contains the updated record data
  saveToDatabase(record);
}}
```

## Configuration

| Property | Type | Description |
| -------- | ---- | ----------- |
| `cellEditable` | `boolean` | Enable cell editing mode. |
| `lockColumnWidths` | `boolean` | Prevent column widths from changing when editing starts. |
| `onCellEdited` | `function` | Callback when a cell value changes. |
| `editor` | `Widget` | Column property specifying the editor widget. |
| `editable` | `boolean` | Column property to disable editing for specific columns. |

See also: [Row Editing](/docs/tables/row-editing), [Inline Edit](/docs/tables/inline-edit)