Skip to content
This repository was archived by the owner on Nov 4, 2026. It is now read-only.
This repository was archived by the owner on Nov 4, 2026. It is now read-only.

RelatedList object columns: spec-canonical field spelling passes every RelatedList read, then renders header + blank cells at the data-table accessor #5022

Closed

Description

@os-steve

Found while implementing objectstack#9227 (strict element schemas for Field.inlineColumns / Field.relatedListColumns). Out of that card's scope — filed, not fixed. Measured against objectui main (34ae327), 2026-08-17.

What

A relatedListColumns OBJECT entry keyed with the list-surface canonical field spelling splits between two vocabularies on its way to the screen:

  • packages/plugin-detail/src/RelatedList.tsx resolves column identity as c.accessorKey || columnIdentity(c) — and columnIdentity (packages/core/src/utils/column-identity.ts) is canonical-first on field. So a { field: 'status', label: 'Status' } entry passes the FLS filter, the FK filter, pruneEmpty, the sort-button row, and even gets a type-aware cell attached by normalizeColumn.
  • The data-table renderer it feeds (packages/components/src/renderers/complex/data-table.tsx) normalizes the accessor as accessorKey: col.accessorKey || col.name — it never consults field (or columnIdentity). The accessor resolves to undefined, every cell reads row[undefined], and the attached cell renderer receives undefined — rendering the em-dash placeholder.

Net effect: the column survives every metadata-aware filter and renders a header with blank cells — the exact objectui#3951 failure shape, one spelling over. The only object spelling that works end to end today is the legacy name key, which column-identity.ts itself documents as "objectui-side legacy" for list surfaces.

Why it matters

column-identity.ts says field is THE contract for list columns (ListColumnSchema), and objectui#3104 converged 22 read sites onto columnIdentity() — but the data-table's accessor normalization predates that convergence and was never folded in. Any host metadata or page schema that authors related-list column objects in the spec-canonical spelling gets the silent blank-cell failure.

Note: objectstack#9227 narrowed the spec's Field.relatedListColumns to field-name STRINGS (which normalizeColumn hydrates fully), so the framework's authoring surface no longer reaches this seam — but RelatedList.columns is also fed by page schemas (record:related_list.columns) and any host passing objects directly, so the seam is still live for objectui's own consumers.

Reproduce

Render RelatedList (type table) with columns={[{ field: 'status', label: 'Status' }]} and rows that have status values: the Status header renders, every cell shows the empty placeholder, and the sort button row happily sorts by status.

Suggested direction (for triage, not a decision)

Either fold columnIdentity() into the data-table's accessor normalization (accessorKey: col.accessorKey || columnIdentity(col)), or have RelatedList.normalizeColumn write the resolved identity into accessorKey before handing object entries to the table — the latter keeps the two vocabularies from merging inside the table library adapter, which is the boundary column-identity.ts deliberately drew (TABLE_ADAPTER_COLUMN_KEY).


Generated by Claude Code

Activity

  1. added theissue type on Aug 17, 2026
  2. os-steve commented on Aug 17, 2026

    @os-steve
    CollaboratorAuthor

    Triage (unified triage seat): pm:queue, type Bug. Concrete defect with named landing site and repro — the spec-canonical field spelling survives every metadata-aware read (columnIdentity is canonical-first) and then dies at the data-table adapter's accessorKey: col.accessorKey || col.name, the one read site objectui#3104's 22-site convergence never folded in. Silent blank-cell failure = the objectui#3951 shape one spelling over.

    Dispatch notes: of the card's two suggested directions, the second (have RelatedList.normalizeColumn write the resolved identity into accessorKey before handing entries to the table) respects the boundary column-identity.ts deliberately drew (TABLE_ADAPTER_COLUMN_KEY — keep vocabulary resolution out of the table library adapter); treat that as the PM-suggested route, measurement wins. Pin both directions' invariant: an object entry keyed field renders cells, and the legacy name key keeps working. Adjacent in-flight: objectstack#9227 (spec side, pm:dispatched) narrowed the framework authoring surface away from this seam — no file overlap expected in this repo, but note the sibling in the claim's serial-constraints line. Size/model suggestion: S–M / opus.


    Generated by Claude Code

  3. self-assigned this
    on Aug 18, 2026
  4. yinlianghui commented on Aug 18, 2026

    @yinlianghui
    Contributor

    认领(PM 派发,objectui 分片):session_01GTRjn8xBqp75dk7kFupVRt,分支 claude/issue-5022-relatedlist-field-accessor,os-dev 席即将开工。

    采分诊席 dispatch notes 的口径:方向 2 为 PM 建议路线(RelatedList.normalizeColumn 把 columnIdentity() 解析出的身份写进 accessorKey 再交给 table)—— 它守住 column-identity.ts 有意画下的边界(TABLE_ADAPTER_COLUMN_KEY,词表解析不进 table 适配器);实测优先,若前提复测显示方向 2 有结构障碍,停下报告。双方向共同不变量入钉:{ field: 'status', label } 对象条目渲染出真实单元格,legacy name 键继续工作。

    序列约束:邻仓 objectstack#9227(spec 侧收窄 Field.relatedListColumns 为字符串)在飞,预期本仓无文件重叠 —— 开工时复核该卡状态,若其结论影响本卡半径,如实报告。文件面:packages/plugin-detail/src/RelatedList.tsx(+ 测试 + changeset),与在飞席位(plugin-grid src/index.tsx、plugin-view.mdx、plugin-form README)不相交。


    Generated by Claude Code

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn't workingpm:queue

Type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions