Form Edit
Grid can be connected to a separate form for editing selected records. This pattern is useful when records have many fields or when you want a clear separation between viewing and editing.
<div controller={PageController}>
<Grid
records={m.records}
selection={{ type: KeySelection, bind: m.selectedId, keyField: "id" }}
columns={[
{ header: "Name", field: "fullName", sortable: true },
{ header: "Phone", field: "phone" },
{ header: "City", field: "city", sortable: true },
{
header: "Notified",
field: "notified",
value: expr(m.$record.notified, (n) => (n ? "Yes" : "No")),
},
{
header: "Actions",
style: "padding: 2px",
children: (
<Button
mod="hollow"
onMouseDown={stopPropagation}
onClick={(e, instance) => {
const id = instance.store.get(m.$record.id)
instance.getControllerByType(PageController).removeRecord(id)
}}
>
Remove
</Button>
),
},
]}
recordAlias={m.$record}
/>
<p class="mt-4">
<Button
onClick={(e, instance) =>
instance.getControllerByType(PageController).addRecord()
}
>
Add
</Button>
</p>
<hr class="my-6" />
<LabelsLeftLayout visible={hasValue(m.form)}>
<strong text={m.form.fullName} class="mb-4" />
<TextField label="Name" value={m.form.fullName} />
<TextField label="Phone" value={m.form.phone} />
<TextField label="City" value={m.form.city} />
<Checkbox label="Notified" value={m.form.notified} />
<Button
onClick={(e, instance) =>
instance.getControllerByType(PageController).saveRecord()
}
>
Save
</Button>
</LabelsLeftLayout>
</div> | Name | Phone | City | Notified | Actions |
|---|---|---|---|---|
| Alice Johnson | 555-0101 | New York | Yes | |
| Bob Smith | 555-0102 | Los Angeles | No | |
| Carol White | 555-0103 | Chicago | Yes | |
| David Brown | 555-0104 | Houston | No | |
| Eva Green | 555-0105 | Phoenix | Yes |
Click a row to select it. The form below displays the selected record’s data for editing.
Loading Form Data
Use a trigger to load the selected record into the form:
this.addTrigger("loadForm", [m.selectedId, m.records], (id, records) => {
const record = records?.find((r) => r.id === id);
this.store.set(m.form, record || null);
});
Saving Changes
Update the records array when the form is saved using updateArray:
import { updateArray } from "cx/data";
saveRecord() {
const form = this.store.get(m.form);
if (!form) return;
this.store.update(m.records, (records) =>
updateArray(records, () => form, (r) => r.id === form.id)
);
}
Preventing Row Selection on Button Click
When using action buttons inside a selectable grid, clicking the button also selects the row. Use stopPropagation on onMouseDown to prevent this:
import { stopPropagation } from "cx/util";
{
header: "Actions",
children: (
<Button
onMouseDown={stopPropagation}
onClick={(e, instance) => {
instance.getControllerByType(PageController).removeRecord(id);
}}
>
Remove
</Button>
),
}
When to Use
Form editing is ideal when:
- Records have many fields that don’t fit in a grid
- You want explicit Save/Cancel actions
- Complex validation is needed before saving
- The form needs additional context or related data
See also: Cell Editing, Row Editing, Inline Edit