Skip to content

Add field configuration option to provide editor#5106

Merged
backspace merged 11 commits into
mainfrom
cs-11383-add-a-per-usage-edit-option-to-field-declarations
Jun 5, 2026
Merged

Add field configuration option to provide editor#5106
backspace merged 11 commits into
mainfrom
cs-11383-add-a-per-usage-edit-option-to-field-declarations

Conversation

@backspace

@backspace backspace commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

This is an outgrowth of #4973, where we want to provide a custom editor for the collection of host routing rules to support a rich realm config editor:

CleanShot 2026-06-04 at 11 26 12@2x

In that context it’s used like this:

@field hostRoutingRules = containsMany(RoutingRuleField, {
    edit: RealmConfigRoutingRulesEditor,
  });

backspace and others added 4 commits June 4, 2026 10:41
A field declaration can supply its own edit component via the
`edit:` option, overriding the FieldDef's `static edit` for that
specific usage.

* Atomic fields (contains / linksTo): the override resolves at
  the field-component layer and replaces the standard edit
  component. The dispatch is gated on fieldType so the field
  descriptor inherited by iterated items inside a containsMany
  doesn't accidentally hijack each item's template.
* containsMany: the override receives `@model` (containing card),
  `@values` (the array), and `@defaultEditor` — a pre-bound
  ContainsManyEditor — so the override can wrap (rather than
  replace) the standard iteration / add / remove / sortable UI.
The override branch in field-component sees the same field descriptor
for both the outer collection render and each iterated item inside
containsMany. Without a gate it would replace each item's edit
template with the collection-level override component, blanking
every row. Restrict it to atomic field types; collection fields
go through their own wrap-style handler.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* linksTo: when `linksToField.edit` is set, render that component
  in place of the default LinksToEditor at the atomic site.
* linksToMany: mirror the containsMany wrap contract — the override
  receives `@model` (containing card), `@values` (the linksToMany
  array), and a pre-bound default LinksToManyEditor as
  `@defaultEditor` so it can wrap (rather than replace) the
  standard iteration / add / remove UI.
One test per field type, asserting:

* contains / linksTo (atomic): the override replaces the default
  edit component for the specific usage; the default editor is
  suppressed.
* containsMany / linksToMany (wrap): the override is invoked with
  a pre-bound `@defaultEditor`, and rendering it produces the
  standard editor so the wrap doesn't have to reimplement
  iteration / add / remove UI.
@github-actions

github-actions Bot commented Jun 4, 2026

Copy link
Copy Markdown
Contributor

Preview deployments

Host Test Results

    1 files  ±0      1 suites  ±0   1h 51m 15s ⏱️ - 2m 1s
2 943 tests +1  2 928 ✅ +1  15 💤 ±0  0 ❌ ±0 
2 962 runs  +1  2 947 ✅ +1  15 💤 ±0  0 ❌ ±0 

Results for commit 0a8201a. ± Comparison against earlier commit ffe5cc0.

Realm Server Test Results

    1 files  ± 0      1 suites  ±0   8m 20s ⏱️ - 4m 53s
1 544 tests  - 15  1 544 ✅  - 14  0 💤  - 1  0 ❌ ±0 
1 635 runs   - 15  1 635 ✅  - 14  0 💤  - 1  0 ❌ ±0 

Results for commit 0a8201a. ± Comparison against earlier commit ffe5cc0.

@backspace backspace changed the title Cs 11383 add a per usage edit option to field declarations Add field configuration option to provide editor Jun 4, 2026
`ember/no-empty-glimmer-component-classes` flags GlimmerComponent
subclasses whose only member is a `<template>`; switching the test
helpers to `TemplateOnlyComponent` removes the empty backing class
and collapses a couple of prettier-flagged call sites onto single
lines.
@backspace backspace marked this pull request as ready for review June 4, 2026 19:17

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f3855b0b6d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread packages/base/field-component.gts Outdated
Comment thread packages/base/links-to-many-component.gts
backspace added 4 commits June 4, 2026 14:45
The view-slot dedup picks a shared component reference when a
FieldDef intentionally aliases its embedded / isolated slot to its
`static edit`, so toggling between formats keeps the same component
mounted. Gating the per-usage override on `!viewSlot` made the
override silently lose to that dedup, contradicting the documented
contract that `{ edit: ... }` replaces the FieldDef's `static edit`
for that usage. Drop the gate so the override always wins in edit
format; toggling embedded↔edit will remount as a result, which is
correct — the consumer opted into a different component.
The standard LinksToManyEditor branch already receives
`...attributes`, so a caller writing
`<@fields.foo class='whatever' data-x='y' />` had those forwarded
to the editor. The override branch dropped them, regressing the
contract for that field type. Splat them onto the override too
(consumers can choose whether to forward them through to
`@defaultEditor`).
@backspace backspace requested a review from a team June 5, 2026 12:50
@habdelra habdelra requested a review from Copilot June 5, 2026 13:11

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a per-field-declaration edit option that lets card authors override a field’s edit component at the usage site (without subclassing the FieldDef), including a “wrap the default editor” contract for collection fields to support richer realm-config editing UIs.

Changes:

  • Extends field options/descriptor shape (card-api.gts) to carry an optional edit override component.
  • Updates field rendering to prefer the per-usage edit override in edit format, with special handling for containsMany/linksToMany overrides via @defaultEditor.
  • Adds integration tests covering atomic and collection override behavior (including @defaultEditor wrapping and attribute passthrough for linksToMany).

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
packages/base/card-api.gts Adds edit to field options/descriptor and wires it into field factory helpers + linksTo edit rendering.
packages/base/field-component.gts Ensures per-usage edit wins for atomic fields in edit format, without breaking collection item rendering.
packages/base/contains-many-component.gts Adds per-usage edit override support for containsMany via a wrap-style @defaultEditor contract.
packages/base/links-to-many-component.gts Adds per-usage edit override support for linksToMany via a wrap-style @defaultEditor contract and forwards attributes.
packages/host/tests/integration/components/per-usage-edit-override-test.gts New integration coverage for atomic + collection per-usage edit overrides, including @defaultEditor wrapping.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread packages/base/contains-many-component.gts
Mirrors the linksToMany fix: the override is the contract a
consumer reaches when supplying `{ edit: ... }`, so it should pass
through `<@fields.foo class='x' data-y='z' />`-style attributes.
The non-edit branch already splats them onto the container, and
the linksToMany override now does too; making containsMany behave
the same way keeps the override contract consistent across field
types. The standard ContainsManyEditor branch is unchanged
(broader cross-format contract change, out of scope here).
@backspace backspace merged commit 56405d5 into main Jun 5, 2026
72 of 73 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants