[6.x] Fix default values and fieldtype meta after saving entries and terms - #15427
[6.x] Fix default values and fieldtype meta after saving entries and terms#15427duncanmcclean wants to merge 3 commits into
Conversation
the file writer drops empty values from root entries and default-locale terms, but the in-memory object keeps them, so `Field::preProcess()` never fell back to the default until the stache was cleared. mirror the writer's rule when extracting publish form values. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmQ7DBwRHtNLUej3bbyMQW
return `meta` from the entry and term update endpoints and apply it in the save pipeline alongside the values, so relationship items added during `EntrySaving`/`TermSaving` render correctly. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmQ7DBwRHtNLUej3bbyMQW
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EmQ7DBwRHtNLUej3bbyMQW
jasonvarga
left a comment
There was a problem hiding this comment.
The PHP half looks right to me — ExtractsFromEntryFields and ExtractsFromTermFields mirror Entry::fileData()'s isRoot() conditional and Term::fileData()'s default-locale-only stripping precisely. I also confirmed the term restructure doesn't lose in-memory TermSaving changes, since LocalizedTerm::data() and inDefaultLocale()->data() both read through to the same underlying Term.
One issue on the JS side that needs fixing before this goes in — the wholesale setMeta() clobbers client-owned slug meta. Details inline.
Non-blocking: both new PHP tests only cover the root/default-locale branch, so nothing exercises the localization side of the new isRoot() ternary.
| if (container && response.data.data?.hasOwnProperty('meta')) { | ||
| container.value.setMeta(response.data.data.meta); | ||
| } |
There was a problem hiding this comment.
This replaces the container's meta wholesale, which drops meta.slug.auto — client-owned state the server never emits.
The chain:
Container.vue'ssetMeta()is a plain replacement (meta.value = newMeta), and itswatch(meta, ...)emitsupdate:meta, which flows back toPublishForm.vue'sv-model:meta.PublishForm.vuethen sends_auto_slug: this.meta.slug?.auto ?? falseon every save — now alwaysfalse.- The only writer of
meta.slug.autois themounted()watcher inSlugFieldtype.vueon$refs.slugify.shouldSlugify. It'simmediate: true, so it fires once on mount and then only whenshouldSlugifychanges. "Save & continue editing" doesn't remount the form andshouldSlugifydoesn't change, so the flag never comes back. Slug.phphas nopreload(), so the server never repopulates it.
So after any save that keeps the form open (Save & continue, autosave, inline/stack saves), EntriesController::resolveSlug() starts taking $request->slug verbatim instead of re-deriving it from the title — which is what its "An auto generated slug lags behind the values it came from" comment exists to prevent. Change the title and save before the debounced slugify settles, and the stale slug gets persisted. Entries only; terms have no _auto_slug handling.
Worth preserving client-owned meta rather than replacing it, similar to how resetValuesFromResponse already preserves revealerFields.
The distinction is narrow, to be clear: Relationship/Assets/Bard/Replicator/Grid meta is server-produced, so refreshing that is exactly the fix you want here. It's only slug's auto that's client-owned.
This pull request fixes two issues with the publish form after saving an entry or term and continuing to edit.
Firstly, it fixes an issue where default values weren't applied to fields that had been saved empty (for example, a grid hidden behind a toggle with
always_save: false), until the Stache was cleared.This was happening because
Entry::fileData()andTerm::fileData()strip null and empty values before writing to disk, but the in-memory object (which is what the save response is built from, and what the Stache caches) keeps them. A hidden grid is processed to[], which isn't null, soField::preProcess()never fell back to the field's default.This PR fixes it by mirroring the writer's rule when extracting publish form values: empty values are dropped for root entries and default-locale terms. Localizations are left alone since explicit nulls are meaningful there.
Secondly, it fixes an issue where relationship values set in an
EntrySavingorTermSavinglistener rendered as broken items after "Save & continue editing", until the page was reloaded.This was happening because the save pipeline re-applied the response's
values, but nothing refreshed the fieldtypemeta, so the Relationship fieldtype had no item data for the newly added IDs.This PR fixes it by returning
metafrom the entry and term update endpoints and applying it in the save pipeline alongside the values.The same missing
metawas also behind #15418: a conditionally hidden nested Replicator withdefault:rows gets fresh row IDs on every request, so after saving, the Assets fieldtypes inside those rows couldn't find their meta and threw, leaving the Control Panel unresponsive until a hard refresh.Fixes #11355
Fixes #11396
Fixes #15418
Replaces #11356