Grid Editing

Set AllowEdit="true" on MainGrid / SubGrid and a toggle labelled Editable appears in the gear-menu overflow. Flipping it on switches every declared column whose cell renderer isn't overridden into an inline editor — auto-dispatched from the column's Dataverse metadata — while a GridTemplateColumn's EditChildContent takes over from its read-mode ChildContent. Edits accumulate as pending row changes in the grid's transactional buffer and only land in Dataverse when the user saves.

Live Demo

A MainGrid over the contact table with AllowEdit="true". Click the gear icon on the toolbar overflow and flip Editable on. The Full Name column swaps its initials-avatar read template for a custom single-field editor that splits user input back into firstname + lastname. The bare Email, Phone, Age, and Account columns each light up with the editor matching their metadata type — TextEdit for the strings, NumberEdit for the integer, LookupEdit for the customer reference — without any per-column wiring.

React example
Blazor example
Anyone can view contacts in the grid below. Log in to create, view, and update your own contacts.
Save Refresh

Page size

102050100
Editable
Full Name
Email
Phone
Age
Account
React TypeScript
Razor

Enabling Editing

Set AllowEdit="true" on the grid. Editing is opt-in per grid — the toggle only appears when the parameter is set, and the toggle itself is only visible when at least one column is editable. While the toggle is off, the grid behaves as a read-only view; while it's on, cells render their inline editors and unsaved changes are tracked per row.

React
Blazor

Why a toggle?

Inline edit changes the cell rendering for every visible row, which is a different read affordance than a static grid. The toggle lets users opt into the edit affordance when they need it (typing a value, tabbing across cells, etc.) and keep the cleaner read affordance the rest of the time. The grid remembers the toggle state for the session.

Automatic editor dispatch

Bare <GridColumn ColumnName="..." /> declarations with no ChildContent auto-dispatch the right inline editor while the grid is in edit mode. The framework reads the column's metadata and picks the editor subclass:

  • String, Memo, EmailAddress, Phone, UrlTextEdit (with format-appropriate validation).
  • Integer, Decimal, Double, BigIntNumberEdit (locale-aware parsing, min/max from metadata).
  • BooleanBoolEdit (rendered as a switch, centered alignment).
  • PicklistChoiceEdit (option-set-driven dropdown, localized labels).
  • MultiSelectPicklistMultiSelectChoiceEdit.
  • Lookup, Customer, OwnerLookupEdit (typeahead-driven, respects target-table allow lists).
  • DateTime, DateOnlyDateTimeEdit.
  • MoneyMoneyEdit (currency-symbol prefix from transactioncurrencyid).
  • File, ImageFileEdit / ImageEdit (drag-drop upload).

Overriding the default editor

Supply ChildContent on a GridColumn to take over both the read-mode display AND the edit-mode editor for that column. Once ChildContent is set, the framework stops auto-dispatching the metadata-driven editor — render whichever editor you want inside the template and gate its visibility off the grid's Editable flag. Standard editors (TextEdit, NumberEdit, ColumnEdit) dropped into the template auto-wire to dirty-tracking and validation via the cascading row context.

React
Blazor

Validation

Each row maintains its own EditContextValidator. Standard editors register with it on mount and surface their errors inline (red underline + tooltip on the cell). The grid's save button is disabled while any row has an unresolved validation error. Validation rules come from the column metadata:

  • RequiredLevel — the column is required, and an empty value blocks save.
  • Format on string columns — email, phone, URL formats enforce shape on top of the type.
  • MinValue / MaxValue on numeric columns — out-of-range values are flagged before save.
  • Custom validation — register additional rules per-form via the EditContextValidator API for cross-field invariants (e.g. "contact must have either email or phone").

Validation on custom widgets

Custom inputs rendered inside ChildContent / EditChildContent that don't extend BaseEdit (e.g. a raw FluentTextField or a third-party widget) don't auto-register with the row's validator. If you need them validated, either drop a standard editor instead of the raw widget, or run validation manually inside the widget's ValueChanged callback before calling editCtx.SetValue.

Save & Cancel

Edits accumulate as pending updates on the row — modified cells get a small "dirty" indicator, deleted rows are strikethrough, and pending-create rows show as new. The grid's toolbar surfaces Save and Cancel buttons whenever there are pending changes: Save commits the batch in one transactional pass; Cancel discards the buffer and reverts each row to its server state. Pair with NewRecordGridButton and DeleteRecordGridButton in the Buttons fragment to add row creation and deletion to the same edit transaction.

React
Blazor

Template-Column Editing

Pair a GridTemplateColumn's read-mode ChildContent with an EditChildContent to make a synthetic / composite column editable. The edit template receives a GridTemplateColumnEditContext — same row context as the read template (editCtx.Row.PrimaryRecord, the optional editCtx.Row.ParentRecord in a SubGrid, editCtx.DependsOnMetadata) plus an imperative editCtx.SetValue(columnName, value) helper.

EditChildContent fires only when the grid is editable (AllowEdit="true" AND the Editable toggle is on) and the row isn't pending-delete. Template columns that omit EditChildContent stay read-only even in edit mode — useful for actions columns that should always render the same buttons.

Pattern 1 — Drop-in standard editors

The most common case: the cell composes from multiple bound columns, and you want to let the user edit each one. Drop the matching <TextEdit> / <NumberEdit> / <ColumnEdit> editors inside EditChildContent — the framework cascades the row's primary record and matching EditContextValidator into that scope, so the editors self-register for dirty-tracking and validation. No extra wiring required.

React
Blazor

Pattern 2 — Custom widget with SetValue

When the editor surface doesn't map 1:1 to a Dataverse column — a single "First Last" text box that parses into two columns, a slider tied to multiple percent fields, a custom date-range picker writing start + end — render your own input and call editCtx.SetValue(columnName, value) for each affected column. The framework routes the write to the correct AliasedTableRecord and fires ValueChanged so dirty-tracking picks the change up.

React
Blazor

Validation on the imperative path

Standard editors dropped into EditChildContent register with the row's EditContextValidator automatically and participate in the framework's validate-before-save gate. The editCtx.SetValue path bypasses that pipeline — values that didn't come from a registered editor aren't validated. If your custom widget needs to enforce constraints, run them inside the ValueChanged callback before calling SetValue, or fall back to the drop-in editor pattern.