Skip to content

finding(components): the only working route from a provider dataSource into a data-table is the properties envelope protocol.md tells authors not to use #5372

Description

@os-support-ai

Found while implementing #5126 / #5337 (PR #5371), which corrects three skill guides that taught data-table + bind. Direction there was settled by inheritance from #5125data-table does not gain bind, the teaching changes — so this is filed separately rather than folded in. It is the measurement anyone weighing that decision again would want, and it is not an argument for re-opening it.

The question

After PR #5371 the guides teach data-table's inline data array, which is correct and renders. That leaves an unanswered one: how does an author put provider data (SchemaRendererProvider dataSource) into a data-table at all, without the host pre-resolving the array into the schema?

Measured

Real SchemaRenderer inside a SchemaRendererProvider holding dataSource = { customers: [ 2 records ] }, columns identical in all three legs, reading tbody td text (objectui@99d8721a3, vitest from the repo root):

legnoderendered body cells
A{ "type": "data-table", "data": "${data.customers}", "columns": [...] }["No results foundTry adjusting your filters or search query."]
B{ "type": "data-table", "properties": { "data": "${data.customers}" }, "columns": [...] }["Ada Lovelace","ada@example.com","Grace Hopper","grace@example.com"]
C{ "type": "data-table", "props": { "data": "${data.customers}" }, "columns": [...] }["No results foundTry adjusting your filters or search query."]

So exactly one of the three spellings works, and it is B.

Why

SchemaRenderer's evaluatedSchema memo evaluates expressions in exactly four places: properties.*, content, props.*, and the visibility / disabled predicates. A top-level key is never evaluated, which kills AArray.isArray is false for the raw ${...} string, so DataTableRenderer falls back to EMPTY_ROWS.

Then the COMPAT hoist copies every properties.* value onto the node's top level. props.* gets evaluated but is not hoisted, and DataTableRenderer destructures data off the node, not off schema.props — which kills C.

B survives because it is the only spelling that gets both halves: evaluated, then hoisted.

Why it is worth recording

skills/objectui/rules/protocol.md opens by telling authors the opposite:

The one exception is the element:* namespace. Those components read their config out of properties / props by design ... Match the envelope to the namespace; do not apply either shape everywhere.

So the one envelope the published rules tell an author not to reach for is the only one that reaches the provider's data, and the two spellings the rules endorse both fail in the shape this repo keeps paying for — no throw, no console line, a header over an empty state. An AI author following the rules file cannot get there; one ignoring it can.

This is also the inverse of the shape #4799 corrected. There the canonical properties spelling was starved while the legacy props alias was fed; here properties is the only fed spelling and the canonical node-level one is starved. Same seam, opposite polarity.

Not proposed here

No fix is proposed and none should be inferred. The plausible directions all cost something and at least one of them was already declined in the neighbourhood:

  1. Evaluate data (or a declared set of array-valued keys) at the node level. Widens what expressions reach, on the generic path, for every component.
  2. Give data-table a bind read. This is the direction finding(components): table 被注册两次,data-display 的 SimpleTableRenderer 被 complex/table.tsx 完全遮蔽 —— 而它是唯一读 bind 的表格渲染器 #5125's ruling declined for its sibling renderer; it would need a new Feature card through the decision inbox.
  3. Rule that host-side resolution is the only supported route, and say so in the guides — the cheapest, and it makes the current teaching complete rather than merely true.
  4. Change nothing and record the measurement, which is what this card does today.

Nothing here is blocked on it and no behaviour is broken; #5126 is not addressed by this card and #5120 remains open as its own separate question about the columns key spelling.

Reproducing

Three nodes above, rendered through SchemaRenderer with a provider; the evaluation order is in packages/react/src/SchemaRenderer.tsx (the evaluatedSchema memo), and the row read is data: rawData = EMPTY_ROWS in packages/components/src/renderers/complex/data-table.tsx.


Generated by Claude Code

Metadata

Metadata

Assignees

Labels

documentationImprovements or additions to documentationdomain:uiobjectui ui stream: fix lands on the published library or apps — objectui execution seatpm:dispatched

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions