CxJS

Row Editing

Grid supports row-level editing where users click Edit to modify a row, then Save or Cancel to confirm or discard changes.

<div controller={PageController}>
  <Grid
    records={m.records}
    lockColumnWidths
    cached
    row={{
      style: {
        background: expr(m.$record.$editing, (editing) =>
          editing ? "lightsteelblue" : undefined,
        ),
      },
      valid: m.$record.valid,
    }}
    columns={[
      {
        header: "Name",
        field: "fullName",
        sortable: true,
        children: (
          <TextField
            value={m.$record.fullName}
            viewMode={expr(m.$record.$editing, (e) => !e)}
            style="width: 100%"
            autoFocus
            required
          />
        ),
      },
      {
        header: "Continent",
        field: "continent",
        sortable: true,
        children: (
          <TextField
            value={m.$record.continent}
            viewMode={expr(m.$record.$editing, (e) => !e)}
            style="width: 100%"
            required
          />
        ),
      },
      {
        header: "Browser",
        field: "browser",
        sortable: true,
        children: (
          <TextField
            value={m.$record.browser}
            viewMode={expr(m.$record.$editing, (e) => !e)}
            style="width: 100%"
            required
          />
        ),
      },
      {
        header: "Visits",
        field: "visits",
        sortable: true,
        align: "right",
        children: (
          <NumberField
            value={m.$record.visits}
            viewMode={expr(m.$record.$editing, (e) => !e)}
            style="width: 100%"
            inputStyle="text-align: right"
            required
          />
        ),
      },
      {
        header: "Actions",
        style: "width: 180px",
        align: "center",
        pad: false,
        children: (
          <PureContainer>
            <Button
              mod="hollow"
              onClick="editRow"
              visible={expr(m.$record.$editing, (e) => !e)}
            >
              Edit
            </Button>
            <Button
              mod="hollow"
              onClick="deleteRow"
              visible={expr(m.$record.$editing, (e) => !e)}
              confirm="Are you sure?"
            >
              Delete
            </Button>
            <Button
              mod="primary"
              onClick="saveRow"
              disabled={expr(m.$record.valid, (v) => !v)}
              visible={expr(m.$record.$editing, (e) => !!e)}
            >
              Save
            </Button>
            <Button
              mod="hollow"
              onClick="cancelRowEditing"
              visible={expr(m.$record.$editing, (e) => !!e)}
            >
              Cancel
            </Button>
          </PureContainer>
        ),
      },
    ]}
    recordAlias={m.$record}
  />
  <p class="mt-4">
    <Button onClick="addRow">Add</Button>
  </p>
</div>
NameContinentBrowserVisitsActions
Alice Johnson
North America
Chrome
45
Bob Smith
Europe
Firefox
32
Carol White
Asia
Safari
28
David Brown
Europe
Edge
51

Click Edit to modify a row. The row highlights and fields become editable. Save commits changes, Cancel restores original values.

How It Works

Row editing uses a pattern where the original record is stored in $record.$editing when editing starts:

editRow(e, { store }) {
  let record = store.get(m.$record);
  store.set(m.$record.$editing, record);
}

saveRow(e, { store }) {
  store.delete(m.$record.$editing);
}

cancelRowEditing(e, { store }) {
  let oldRecord = store.get(m.$record.$editing);
  store.set(m.$record, oldRecord);
}

viewMode Property

Form fields use viewMode to toggle between display and edit modes:

{
  header: "Name",
  field: "fullName",
  children: (
    <TextField
      value={m.$record.fullName}
      viewMode={expr(m.$record.$editing, (e) => !e)}
      style="width: 100%"
      required
    />
  ),
}

When viewMode is true, the field displays as text. When false, it becomes an editable input.

Row Highlighting

Use the row property to style the editing row:

<Grid
  row={{
    style: {
      background: expr(m.$record.$editing, (editing) =>
        editing ? "lightsteelblue" : undefined
      ),
    },
    valid: m.$record.valid,
  }}
/>

The valid property tracks form validation state for the row.

Action Buttons

Toggle button visibility based on editing state:

{
  header: "Actions",
  children: (
    <PureContainer>
      <Button onClick="editRow" visible={expr(m.$record.$editing, (e) => !e)}>
        Edit
      </Button>
      <Button
        onClick="saveRow"
        disabled={expr(m.$record.valid, (v) => !v)}
        visible={expr(m.$record.$editing, (e) => !!e)}
      >
        Save
      </Button>
      <Button onClick="cancelRowEditing" visible={expr(m.$record.$editing, (e) => !!e)}>
        Cancel
      </Button>
    </PureContainer>
  ),
}

See also: Cell Editing, Inline Edit, Form Edit