Skip to content

Parent Tree View developer and API guide

Parent Tree View is an additive Entity UI runtime contract. A bootstrap returns either a Flat page or a Tree root page, never both. Child requests always echo the resolved surface revision so stale branches cannot be merged.

  • Authenticate against the target workspace API host.
  • Resolve the Entity Definition and configured Tree Table Surface, whether default or explicitly selected.
  • Use the installed Runtime and Configuration OpenAPI documents as the authoritative schemas and enum source.
  • Never supply a parent-field id or key to a runtime child route; the server resolves structural metadata from the Table Surface.
ContextBootstrapChild pageAdditional root page
Data ExplorerPOST /api/workspace/entity/{entityIdOrKey}/ui/hosted/table/bootstrap?hostSurface=EntityListPOST /api/workspace/entity/{entityIdOrKey}/ui/hosted/table/tree/children?hostSurface=EntityListRepeat bootstrap with the next query page.
Direct tablePOST /api/workspace/entity/{entityIdOrKey}/ui/table/bootstrap?tableSurfaceKey={optionalKey}POST /api/workspace/entity/{entityIdOrKey}/ui/table/tree/children?tableSurfaceKey={optionalKey}Repeat bootstrap with the next query page.
Generic Reference pickerPOST /api/workspace/entity/{entityIdOrKey}/ui/reference-picker/table/bootstrap?tableSurfaceKey={optionalKey}POST /api/workspace/entity/{entityIdOrKey}/ui/reference-picker/table/tree/children?tableSurfaceKey={optionalKey}Repeat bootstrap with the next query page.
Persisted Reference LookupPOST /api/workspace/entity/{sourceEntityIdOrKey}/ui/form/{sourceFormSurfaceId}/items/{formItemId}/lookup-table/bootstrapPOST /api/workspace/entity/{sourceEntityIdOrKey}/ui/form/{sourceFormSurfaceId}/items/{formItemId}/lookup-table/tree/childrenRepeat bootstrap with the next query page.
Details related-data navigationPOST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/block?hostSurface=DetailsPage&instanceId={hostInstanceId}POST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/related/tree/children?hostSurface=DetailsPage&instanceId={hostInstanceId}POST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/related/tree/roots?hostSurface=DetailsPage&instanceId={hostInstanceId}
Details/Drawer hosted-layout blockPOST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/block?hostSurface={DetailsPage-or-Drawer}&instanceId={hostInstanceId}POST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/related/tree/children?hostSurface={DetailsPage-or-Drawer}&instanceId={hostInstanceId}POST /api/workspace/entity/{hostEntityIdOrKey}/ui/hosted-layout/related/tree/roots?hostSurface={DetailsPage-or-Drawer}&instanceId={hostInstanceId}

The public Runtime OpenAPI documents every bootstrap and child request. A related root or child request includes its layout item and opaque bootstrap ContextRevision; the server re-resolves the host record, block, binding, target default table, and relation eligibility scope before querying.

EntityTablePageBootstrap obeys this invariant:

Resolved resultPageTreePageModel.TreeView
Flatnon-nullnullnull
Treenullnon-nullnon-null
Missing surfacenullnullno usable model

A client must reject both/neither page variants for a usable model. It must not call the flat Entity Instance list endpoint as a fallback.

Each TreePage.Items[] element contains:

  • Instance: the ordinary materialized row and permissions;
  • ChildCount: exact eligible direct-child count;
  • IsAncestorContext: true only when retained for a matching descendant;
  • HierarchyIssue: None, SelfParentCut, or CycleCut.

Issue values are row-local and contain no related record id.

For hosted Data Explorer or a generic picker:

{
"ParentInstanceId": "<expanded record id>",
"ExpectedTableSurfaceId": "<Model.Id from bootstrap>",
"ExpectedTableSurfaceRowVersion": "<Model.RowVersion from bootstrap>",
"Query": {
"Page": 1,
"PageSize": 25,
"ArchiveMode": 0,
"Filter": null,
"Sort": [
{
"Field": { "EntityFieldDefinitionId": "<subject field id>" },
"Direction": 0
}
],
"Include": null
}
}

Copy the exact query field-reference shape and enum values from the installed OpenAPI. Reuse the same Filter, Sort, ArchiveMode, and Include for roots and all child pages. Only Page changes within one sibling set.

A persisted Lookup child request uses a flat request object rather than the generic request’s nested Query object:

{
"ParentInstanceId": "<expanded record id>",
"ExpectedTableSurfaceId": "<Model.Id from bootstrap>",
"ExpectedTableSurfaceRowVersion": "<Model.RowVersion from bootstrap>",
"ExpectedLookupFormSurfaceRowVersion": "<LookupFormSurfaceRowVersion from bootstrap>",
"Page": 1,
"PageSize": 25,
"ArchiveMode": 0,
"Include": null,
"Filter": null,
"Sort": []
}

The source Form Surface id and form item id remain route segments. The server re-resolves the persisted item, its Lookup selector, target entity, role selector, and current Form/Table revisions, preserves the validated request Filter, and rejects a stale Form Surface revision. Moltaro V1 has no separate declarative per-form-item row-constraint model; do not invent or emulate one in client code.

For persisted Lookup, the route entity is the source entity that owns the Form Surface and Reference item. The target entity and Tree Table Surface are resolved from that persisted source item; do not substitute the target entity in the route.

Related Details/Drawer root and child requests do not accept Query, Filter, Sort, or Include. They carry the server-owned hosted context instead. For a child page:

{
"LayoutItemId": "<related layout item id>",
"ExpectedContextRevision": "<ContextRevision from bootstrap>",
"ParentInstanceId": "<expanded record id>",
"ExpectedTableSurfaceId": "<Table.Id from bootstrap>",
"ExpectedTableSurfaceRowVersion": "<Table.RowVersion from bootstrap>",
"Page": 1,
"PageSize": 25,
"ArchiveMode": 0
}

The related root-page request uses the same fields without ParentInstanceId. Only Page changes while appending a root sibling page. The server re-resolves the host record, layout block, binding projection, eligibility scope, default Table Surface, and configured sort from the opaque context. Do not add direct-query members: the public schemas reject unknown properties.

The hierarchy runtime reuses Entity Instance Query validation and execution: DisplayName, ordinary fields, Reference target DisplayName, joined supported paths, multiple sort items, direction, null semantics, and stable Id ASC tie-breaking. Generic queryability rules remain unchanged; the server’s narrow use of a relation-activated Parent as a structural edge does not make it available to arbitrary filters or sorts.

Filtering first determines direct matches, then adds visible ancestor closure. TotalCount and HasNextPage describe the requested sibling set. Root and child paging are independent, one-based, and capped at 250. Embedded related tables append additional roots through the related tree/roots route; their root-level More control is not the child More row of any branch.

HTTPMeaningClient behavior
400Invalid request, selector, field, Tree configuration, or unavailable configured search (moltaro.search.notAvailable)Display the stable API error; preserve the query for retry; do not flatten.
403Caller cannot access the definition/contextStop and preserve no hidden metadata.
404Definition or requested readable parent/context not foundRemove/reload that branch as appropriate.
409Expected Table, Lookup Form, or related host-context revision is staleAbort children, clear the tree, bootstrap again.

Automation branches on stable Errors[].Code and Errors[].Field, not English messages.

The parent is an ordinary Reference value. Use supported Entity Instance create or patch services and the record’s current RowVersion; do not write the physical parent column directly. Read the changed record and refresh the Tree bootstrap after a successful mutation.

V1 does not reject cycles at write time. If business policy requires one root, allowed parent types, maximum depth, or cycle prevention, enforce it in the workspace’s supported C# business logic before save. Runtime normalization is a safe presentation boundary, not a substitute for domain validation.

Expansion and selection are distinct operations. Send only explicit record ids on confirmation. Do not select a synthetic Load-more row or infer descendants. In Data Explorer, this selected-record workflow is desktop-only: the narrow/mobile card presentation deliberately exposes neither record-selection controls nor the bulk-action bar. This restriction does not apply to a picker, whose purpose is explicit record selection. The Data Explorer responsive transition clears desktop selected ids and dismisses pending group-action UI; selection does not reappear when the viewport returns to desktop. For persisted Lookup, never replace its dedicated routes with the generic picker route: doing so would discard the persisted source-item/selector context and its Form Surface revision guard.

Data Explorer export is desktop-only. Query export uses the ordinary Entity Instance query, so context-only ancestors are excluded; selected export uses exact ids. Narrow/mobile Data Explorer exposes neither query export nor selected-row export. There is no V1 endpoint for exporting the current depth-first expanded projection.

  1. Read the installation-local Configuration OpenAPI.
  2. Read Table configuration options and select a returned Ready parent field.
  3. Configure TreeView on a Table Surface and decide whether it should be the entity default.
  4. If needed, assign it through Entity List MainTableSelectors and a Reference item with Lookup input. Resolve any List/LongList dependency before making it default.
  5. Read both configurations back.
  6. Bootstrap Data Explorer/direct, each affected Details/Drawer related block, and the relevant picker route.
  7. Verify one root page, one child page, related scope, one sibling sort, and one descendant filter.
  8. Repeat with an ordinary reader when a test identity exists.
  9. Report V1 limitations; do not invent Group By, List/LongList Tree selection, subtree operations, or WYSIWYG tree export.