DomainFrameEditor
Defined in: js-api/src/ui/domains/domains-editor.ts:310
THE single writer of a domain frame's editing state.
It wraps a DataFrame produced by table.queryDf(...) and attaches three
invisible service columns — DomainFrameEditor.STATE_COLUMN,
DomainFrameEditor.CHANGES_COLUMN, DomainFrameEditor.ERRORS_COLUMN —
that hold everything about the pending batch: which
rows are new/modified/deleted, the ORIGINAL value of every changed cell, and
the per-cell validation errors. Grids, forms and the save pipeline all read
that one state; nothing keeps a parallel store.
const editor = await DomainFrameEditor.create(grok.dapi.domains.table('grit.issue'));
editor.setValue(0, 'title', 'New title'); // tracked, validated, highlighted
await editor.save(); // ONE /transaction
Every service column is tagged out of binary AND csv export, so the state is
memory-only: a saved project, toByteArray(), toCsv(), an export or a
batch() upload built from the frame never carry it.
Writing. Go through setValue (programmatic) or beginEdit + commitEdit (an in-grid edit, where the grid has already written the cell). Writing a cell directly on the DataFrame bypasses the tracking and the value is silently NOT saved.
Deleted rows stay in the frame and are hidden by ANDing them out of the filter bitset on every filter recomputation, so undoing a delete (unmarkDeleted) is trivial and row order never moves. The mirror case — a row the server already deleted, staged to come back by markRestored — stays VISIBLE for the same reason: it is a pending change the user must see.
Refreshing discards edits — BY DESIGN. refresh re-runs the query and rebuilds the frame and its state from scratch; there is no merge and never will be. Deciding whether it is safe to refresh is the CALLER's job: read isDirty / subscribe to onDirtyChanged and prompt (save / discard / cancel) before calling it. A component that refreshes on a timer or on a route change without that check WILL eat a user's batch edits.
Implements
Properties
| Property | Modifier | Type | Default value | Description | Defined in |
|---|---|---|---|---|---|
access | readonly | DomainAccess | undefined | Effective access of the current user, SNAPSHOT when the editor was created — what read-only degradation and the writable-column payload filter derive from. A later grok.dapi.domains.invalidateUiCaches() (or a grant change) does NOT reach an existing editor: re-create it to pick the new permissions up. | js-api/src/ui/domains/domains-editor.ts:398 |
client | readonly | DomainTableClient | undefined | The table the frame's rows belong to. | js-api/src/ui/domains/domains-editor.ts:392 |
quiet | readonly | boolean | undefined | See DomainFrameEditorOptions.quiet. | js-api/src/ui/domains/domains-editor.ts:379 |
CHANGES_COLUMN | readonly | "~changes" | '~changes' | JSON column holding the ORIGINAL values of changed cells only (sparse). | js-api/src/ui/domains/domains-editor.ts:314 |
DRAFT_ID_PREFIX | readonly | "~new:" | '~new:' | Prefix of the id addRow stamps into a row that does not exist on the server yet: ~new:<uuid>. Another row (of this or of another editor in the same DomainSession) may hold it in a ref column — buildOps turns it into the transaction's $ref and the server resolves it. | js-api/src/ui/domains/domains-editor.ts:328 |
ERRORS_COLUMN | readonly | "~errors" | '~errors' | JSON column holding per-cell DomainCellErrors. | js-api/src/ui/domains/domains-editor.ts:316 |
LIVE_ROWS | readonly | RegExp | undefined | The referential refusal the server sends back, which names the child table and the column pointing here (DomainRepository._checkDeletable) — restrictRefusal says it in the user's words. | js-api/src/ui/domains/domains-editor.ts:333 |
SERVICE_COLUMNS | readonly | readonly string[] | undefined | The three service columns an editor attaches — every one of them tagged out of binary AND csv export, so the editing state can never reach a saved project, an export, an upload, or a batch() fed from the frame. | js-api/src/ui/domains/domains-editor.ts:321 |
STATE_COLUMN | readonly | "~state" | '~state' | Row state column: `'' | 'new' |