Editable data grids
A data grid presents an array of objects as comparable rows and columns while the controlled value remains a plain JSON array. Order lines, routing rules, inspection records, and node parameter mappings fit this layout.
{
"routes": [
{
"id": "vip",
"condition": "customer.level = vip",
"operator": "equals",
"destination": "sales"
},
{
"id": "failed",
"condition": "execution.status",
"operator": "equals",
"destination": "review"
},
{
"id": "support",
"condition": "message.category",
"operator": "contains",
"destination": "support"
}
]
}The example enables bulk paste, fill down, cross-column filtering, single-column sorting, dialog draft editing, and multi-row selection. Sorting and filtering change only the current view. Paste, fill, and row drafts update value once after validation. Canceling or pressing Escape produces no controlled-value change.
UI node properties
A data grid is a repeater bound to an array of objects, with direct child fields forming its columns.
Read-only state is controlled by the FormRenderer readOnly property. Editing, selection, and bulk operations are disabled when read-only, while sorting and filtering remain available.
Virtualization properties:
Every property is an explicit switch. Existing documents with layout: "data-grid" need no migration. Omitted features remain disabled, and editMode still defaults to "inline".
Structure and Schema
The compiler rejects these structures:
- A
data-gridthat is not arepeater. - A Schema that is not an array of objects.
- No direct field columns, or a direct child that is not a
field. dataGridon another layout.- Unsupported values for
editMode,selection,sorting,filtering,paste,fill, orvirtualization.mode. fill: "down"withoutselection: "multiple".- Virtual scrolling without
editMode: "dialog". - A
viewportHeightoroverscanvalue that is not an integer in the allowed range.
A direct column can still bind to a nested property, such as /properties/routes/items/properties/when/properties/equals.
Editing modes
Inline editing
editMode: "inline" renders real fields directly in cells. Every field change immediately returns the complete array. Use it when there are few columns, inputs are short, and horizontal continuous entry matters.
Dialog draft editing
editMode: "dialog" shows field summaries in the table and opens a guarded row-level task through Edit:
- Clone the current row on open without changing the host value.
- Continue using real field components, row rules, and row data sources in the dialog.
- Run synchronous Schema and rule validation before saving, keep errors on their fields, and focus the first error.
- Return the complete array once after a successful save.
- Discard the draft on cancel, close, or Escape.
- If the host replaces the same row while it is being edited, prevent overwriting and require reopening the latest value.
New rows also use the draft flow. When itemKey points to a required string property, the runtime gives new rows a business identifier separate from UI state; it does not rewrite existing rows.
Host asynchronous validation continues after the row enters the controlled value, following field-blur, wizard-step, or final-submit protocols. The dialog itself does not store remote drafts.
Multi-row selection and deletion
selection: "multiple" adds row checkboxes, select all, and bulk deletion. The selection set uses stable runtime row identities. It is not written to form values and is never submitted or serialized.
Bulk deletion has two steps: first show the number of rows to remove, then confirm submission. The result always respects minItems; if deletion would cross the lower bound, the button is disabled and shows the number of rows that must remain. Moving a row preserves selection, while host removal automatically expires that row's selection.
Persistence, permission checks, and remote operations remain host-managed. Form Renderer only produces a new controlled array.
Bulk paste
paste: "append" adds “Paste rows” to the grid toolbar. The dialog does not request system clipboard permission; it accepts only text the user deliberately pastes. Input, parsing preview, and error state do not change controlled values.
The dialog lists column order explicitly. Each tab-separated cell maps in order to an editable column. hidden, calculated, matrix-single, and matrix-multiple do not become paste columns. A direct UI child field may bind a nested property; parsed values are written to the row object by relative path.
TSV parsing rules:
- Support
LFandCRLFline endings. - Double-quoted cells can contain tabs and newlines.
- A double quote inside a cell is written as
"". - Ignore rows in which every cell is empty.
- Accept at most 1,000 rows and 256 KiB per operation, without exceeding the Schema's
maxItems. - A row cannot contain more cells than there are editable columns.
The Schema type determines cell conversion:
enum is checked after type conversion. An empty non-string cell preserves the row Schema's default value; an empty string cell writes an empty string. Automatic itemKey identities and object defaults still come from the repeater's creation logic.
After “Append data” is selected, parsed rows merge with the existing array and run through complete Schema, rule, and computation evaluation. If any row fails, the first error is shown and the array remains unchanged. If all pass, the fully evaluated array is returned once.
Fill down
fill: "down" depends on selection: "multiple". Designer enables multi-row selection when fill down is enabled and disables fill down when multi-row selection is disabled. The compiler rejects imported documents that do not satisfy this dependency.
Operation order:
- Select at least two currently visible rows.
- Open “Fill down.”
- Choose an editable column.
- Confirm the source value and target row count.
- Write the complete array once after validation passes.
The current sort and filter results determine visible order. The first visible selected row is the source; all remaining visible selected rows are targets. Selected rows hidden by a filter are not changed. Nested object and array values use structural cloning. If the source property is absent, the same path is removed from each target row.
The dialog snapshots source and target rows when opened. If the host replaces, removes, or changes any related row before confirmation, fill stops on a conflict and never overwrites the current controlled value with an old snapshot. The fill result then runs whole-grid Schema, rule, and computation evaluation; any error cancels the entire write.
Sorting and filtering
sorting: "single" gives each column heading a three-state sort: ascending, descending, and original order. Numbers use numeric comparison; text uses the current locale's natural order; empty values always sort last. Narrow containers replace hidden table headings with a sort selector synchronized to the column contract.
Sorting affects only the current Renderer and never reorders or returns the controlled array. Row edits, deletion, and error paths remain bound to original array indices. Move-up and move-down buttons are disabled while sorting or filtering is active; true array order can be changed only after restoring the complete original view.
filtering: "search" matches keywords across formatted text in all visible columns without reading undisplayed properties. Every keyword must match the same row. Matching is case-insensitive and applies Unicode normalization. Result counts and the empty-results recovery action use localized copy.
Select all after filtering selects only currently visible rows. Previously selected rows hidden by a filter remain selected. “Add a row” clears the filter first so the new row is not hidden immediately. Form validation errors also restore the complete view, allowing the error summary to locate and open the relevant row.
When inline editing and sorting are both enabled, the currently focused row retains its position until blur to prevent it jumping during input. It is re-sorted using the latest value after blur. Read-only forms retain sorting and filtering while editing, selection, and row actions stay disabled.
Row virtualization
virtualization.mode: "rows" constrains the grid to a fixed-height scroll region and mounts only the current window plus buffered rows before and after it. Sorting, filtering, select all, bulk deletion, paste, fill, Schema validation, and controlled values still process the complete array; the virtual window does not narrow the data range.
{
"rows": 500,
"first": {
"id": "route-001",
"condition": "payload.segment.001",
"operator": "equals",
"destination": "sales"
},
"last": {
"id": "route-500",
"condition": "payload.segment.500",
"operator": "contains",
"destination": "support"
}
}The example holds a controlled array of 500 rows. Its initial page output includes only enough rows to cover the 420px viewport and buffer. Scrolling replaces the window using measured row heights. The desktop table and narrow-container row cards share the same window calculation.
Virtualization requires dialog editing. Inline inputs are never unmounted by scrolling out of the window, and row drafts do not depend on the virtual row's mount lifecycle. Designer switches to dialog editing automatically when virtual scrolling is enabled and removes virtualization when switching back to inline editing. The compiler enforces the same constraints on imported documents.
Runtime behavior:
- Initial server rendering uses a deterministic row-height estimate. After client mount,
ResizeObserverupdates actual heights for desktop rows and mobile cards. - Column headings remain sticky inside the desktop scroll region. Mobile continues to use row cards with complete field labels.
aria-rowcountdescribes the complete result count, mounted rows use globalaria-rowindexvalues, and spacer regions do not enter the accessible row model.- The scroll region is keyboard-focusable. Home, End, Page Up, and Page Down move to the beginning, end, or neighboring viewport, while static instructions tell assistive technology the full row count and available keys.
- When the error summary targets an unmounted row, the runtime first scrolls to and mounts it, then opens its row dialog and focuses the error field.
- Filter and sort changes reset the window to the beginning of the results so it cannot retain a scroll position beyond the new result range.
- New rows and bulk appends still produce a complete controlled array. If the current filter allows a target row to appear, the grid scrolls to its new position automatically.
viewportHeight controls the embedding panel's vertical footprint. A compact settings panel typically uses 320–480px; full-page data entry can use 560–720px. overscan changes only the scroll buffer and should not grow with the total array length.
Designer
The “Data grid” preset creates Name, Quantity, and Notes columns. The properties panel provides:
- Switching between card rows and a data grid.
- Switching between inline and dialog draft editing.
- A virtual-scrolling switch and scroll-region height.
- A multi-row selection switch.
- A bulk-paste switch.
- A fill-down switch.
- A single-column sorting switch.
- A cross-column filtering switch.
- Renaming, replacing the component, reordering, duplicating, and removing standard field columns.
Switching back to card rows removes the dataGrid policy so grid-only configuration is not left on another layout. Preview uses the real Renderer, with the same value shape as an embedded host.
Responsive behavior and accessibility
Desktop retains a native table, column headings, row headings with scope="row", and explicit row-action names. Virtual grids add complete aria-rowcount and global aria-rowindex values. Row editing, paste, and fill use native <dialog> elements that trap focus while open, focus the message on error, and restore focus to the trigger when closed. Paste preview uses a semantic table; column order, input labels, source value, and target count all have explicit names.
At Form container widths of 520px or less, each row becomes a card with field labels. The decision uses the embedding container—not the browser viewport—so sidebar, node-panel, and dialog hosts behave consistently. Dialog fields follow 12-column width settings and collapse to one column in narrow containers.
Current boundaries
The current implementation covers inline editing, dialog drafts, single-column sorting, cross-column filtering, multi-row selection, confirmed deletion, TSV append, fill down, dynamic-row-height virtualization, stable row identities, and item-count boundaries. Reading or exporting CSV files, authorization, and remote batch processing are host capabilities and cannot be enabled implicitly through undeclared properties.
Questionnaire matrices with shared options use matrix-single or matrix-multiple, not the data-grid layout.
