feat: render broken-link placeholder per element in linksToMany#4983
Merged
habdelra merged 18 commits intoMay 27, 2026
Merged
Conversation
The plural `linksToMany` view path and both link editors (standard + compact) now read `getRelationship` once per render and dispatch `BrokenLinkTemplate` for each slot whose relationship is `error` or `not-found`; present, not-loaded, and not-set slots keep their existing per-item render. Each placeholder occupies its own item container, so one broken element no longer breaks the surrounding list. Stability is preserved by leaving the iteration keying untouched — the view path still keys on the stable per-child component identity and the editors on their index / box identity. The broken-link state only feeds an inner branch, and the relationship read is pure (it never retriggers the lazy loader) and returns a fresh array that is never used as an each key. This keeps per-slot identity stable when state hasn't changed, so a sibling field staying focused mid-edit is never torn down by a broken neighbor. In edit format a broken element shows the placeholder plus the existing remove affordance, so a dead reference is visible and clearable rather than rendering as a broken card. `BrokenLinkTemplate` now accepts splattributes so callers can attach per-element hooks/attributes to the placeholder root. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Contributor
There was a problem hiding this comment.
Pull request overview
Extends the per-element broken-link placeholder pattern (previously added for singular linksTo in #4979) to plural linksToMany fields. Each broken slot in a linksToMany list now renders BrokenLinkTemplate in its own item container while present siblings render normally, in both view and edit (standard + compact) paths.
Changes:
- Add
brokenSlotsForhelper and per-slot broken-link rendering to thelinksToManyview path, standard editor, and compact editor — keying{{#each}}on existing stable identities to preserve focus stability. - Export
brokenLinkFormatfromcard-apiand add splattributes (Element: HTMLDivElement,...attributes) toBrokenLinkTemplate. - Add integration test coverage for mixed lists,
link-errorsentinel, fitted footprint, render-count convergence, edit removal, and DOM identity stability across unrelated re-renders.
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/base/links-to-many-component.gts | Per-slot broken-link dispatch in view path + standard/compact editors, plus brokenSlotsFor helper. |
| packages/base/default-templates/broken-link-template.gts | Accept splattributes on the root div for per-element hooks. |
| packages/base/card-api.gts | Export brokenLinkFormat so the plural component can reuse the format mapping. |
| packages/host/tests/integration/components/linksto-many-broken-link-placeholder-test.gts | New integration tests covering plural broken-link rendering, removal, and render stability. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…n-link-placeholder-per-element-in-linkstomany
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
lukemelia
approved these changes
May 27, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Preview
A
linksToManyof three pets where the middle reference is broken (synthetic 404). Each view format (fitted / embedded / atom) and the edit editor render the broken element as a per-element placeholder while the present siblings render normally. Synthetic URLs only.Summary
The plural
linksToManyview path and both link editors (standard + compact) now readgetRelationshiponce per render and dispatchBrokenLinkTemplateper slot whose relationship iserrorornot-found. Sibling states keep their existing render paths:Each placeholder occupies its own
.linksToMany-itemContainer, so a single broken element no longer breaks the surrounding list. The view-path placeholder adopts the list's effective format (mapped throughbrokenLinkFormat); the editors render it at the item footprint (fittedstandard /atomcompact) alongside the existing remove affordance, so a dead reference is visible and clearable rather than rendering as a broken card.Stability
This field is sensitive to component stability — an unnecessary re-render in edit format can steal focus from an input as the user types. The change is built to avoid that:
{{#each}}keying is left untouched: the view path still keys on the stable per-child component identity, the editors on their index / box identity. The broken-link state only feeds an inner{{#if}}branch.getRelationshipis a pure read (it never retriggerslazilyLoadLink) and is read once per render via{{#let}}; its result is a fresh array that is never used as an each key.Net effect: per-slot identity stays stable when state hasn't changed, so a broken neighbor never tears down a focused sibling.
BrokenLinkTemplatenow accepts splattributes so callers can attach per-element hooks/attributes to the placeholder root.Stacked on #4979 (singular
linksToplaceholder), reusing itsBrokenLinkTemplatedispatch +brokenLinkFormatplumbing. Base retargets tomainonce the parent merges.Ticket: CS-11226
Test plan
New
tests/integration/components/linksto-many-broken-link-placeholder-test.gts(7/7 passing locally):link-errorsentinel element renders the error placeholder (fitted footprint) with its broken URLRegression: the full
links-filtered host suite is green locally (221/221), coveringoperator-mode | links, thelinksTo/linksToManycard-basics and serialization paths, and the singular broken-link placeholder suite. Hostlint:types(glint) and base hbs lint are clean.