Skip to content

fix: keep newly added singular embeds across form changes - #155

Merged
tfwright merged 1 commit into
mainfrom
fix/singular-embed-presence
Oct 15, 2026
Merged

tfwright merged 1 commit into
mainfrom
fix/singular-embed-presence

Conversation

@tfwright

@tfwright tfwright commented Oct 15, 2026 •

Copy link
Copy Markdown
Owner

A singular embed added with the "+" button disappeared on the next form change if none of its fields rendered a named input. This happens with an embed whose only fields are arrays with no values yet: ArrayInput renders hidden inputs only for existing items. For example, pressing Enter in the array input blurs it, which fires a change event, and the section collapses before the item is added.

On each validate, Resource.change rebuilds the changeset from the record plus the form params. A singular embed is cleared when its drop param is present, initialized to %{} when its sort param is present (sent only by the "+" button), and otherwise passed to cast_embed. With no key for the embed in the params, cast_embed leaves the field unchanged, so it falls back to the record's nil.

embed_form no longer passes skip_hidden={true} to inputs_for, so the hidden fields Phoenix renders are back:

  • _persistent_id keeps a singular embed's key in the params, so cast_embed keeps the embed.
  • Embeds with a primary key now send their id. cast_embed then updates existing entries instead of treating each one as new and replacing it, so ids are preserved across saves.

skip_hidden was added in a3a12a7. Back then, removing a singular embed sent params[field] = "", which would have conflicted with nested hidden fields under the same key. The drop param has since replaced that input and is checked first in Resource.change, so removal still works.

Added an array-only private_data embed to the test User schema, plus a container test. The test adds the embed through its sort param, sends another change without it, and asserts that the embed's array input is still rendered. The test fails without the fix.

Also checked in the dev app with temporary schema changes:

  • Array-only singular embed: typing a value and pressing Enter keeps the section and adds the value, and saving persists it. Before the fix, the section collapsed.
  • Singular embed with an id (settings): editing a field and saving keeps the same id.
  • Plural embed with ids (previous_versions with a primary key): reordering by drag and drop saves the new order with both ids kept, and removing an entry drops the right one and keeps the other's id.

A singular embed added with the "+" button disappeared on the next form
change when none of its fields rendered a named input, e.g. an embed with
only array fields and no values yet. The change params then had no key
for the embed, so cast_embed fell back to the record's nil value.

Stop skipping the hidden fields inputs_for renders. The _persistent_id
keeps a singular embed's key in the params, and embeds with a primary key
now send their id, so cast_embed updates existing entries instead of
replacing them. skip_hidden only existed to keep these fields from
conflicting with the old empty-string removal input, which the drop param
has since replaced.
@tfwright
tfwright force-pushed the fix/singular-embed-presence branch from a4566e8 to 0d56f4e Compare October 15, 2026 19:09
@tfwright
tfwright marked this pull request as ready for review October 15, 2026 19:15
@tfwright
tfwright merged commit 08424fa into main Oct 15, 2026
6 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.

1 participant