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> | Name | Continent | Browser | Visits | Actions |
|---|---|---|---|---|
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