MutationObserver breaks ACF flexible content collapsed-state memory
-
Plugin 1.4.0 · ACF PRO 6.8.10 · WordPress 7.1 Summary
GREAT plugin, first off.
With this plugin active, ACF’s flexible content field loses its collapsed-layout memory:
every layout renders expanded on each page load. Deactivating the plugin restores the
behavior immediately. The page I’m editing has ~56 flexible content layouts, so this is
the difference between a usable editor screen and an unusable one. Steps to reproduce- A post type with an ACF PRO flexible content field holding many layouts.
- At least one of those layouts contains a Table field.
- Collapse some or all layouts. Reload the page.
Expected: layouts return collapsed.
Actual: every layout is expanded again. What I foundACF PRO stores flexible content collapse state in localStorage under the key “acf”,
ascollapsedLayouts-<postID>, handled by thethis.collapsedLayoutsmodel in
assets/build/js/pro/acf-pro-input.min.js. That model builds its storage key like this:key: function(key, context) { // context = "load" or "save" var count = this.get(key + context) || 0; count++; this.set(key + context, count, true); if (count > 1) key += '-' + count; return key; }So if the same field asks for its state more than once in a single page load, the
second request gets a DIFFERENT key with a “-2” suffix. Load and save keep separate
counters, so reads and writes can end up on opposite sides of that suffix.That is exactly what I see in localStorage with the plugin active:
collapsedLayouts-1511: { field_610ac7050d4ff: Array(56), field_610ac7050d4ff-2: Array(55) }One field, two entries. With the plugin deactivated, only the unsuffixed key appears
and collapse state persists correctly. Suspected causejs/init.js attaches a MutationObserver to the entire document, unconditionally, whether
or not a Table field is present on the screen:mutationObserver.observe( document.documentElement, { childList: true, subtree: true, });Each batch re-arms a 250ms timer that calls update_tables() -> each_table(), which then
mutates the DOM itself (adds classes, injects .acf-table-wrap) and so re-triggers its own
observer. On an ACF admin screen with a large flexible content field, that churn overlaps
the window in which ACF initializes the field, and the field ends up initialized more than
once — which mints the suffixed key above.I have not instrumented the double initialization directly; that part is inferred from
ACF’s key-suffixing behavior plus the observed “-2” entry. What is directly confirmed is
that the “-2” key appears only while this plugin is active. Suggested fixScope the observer rather than watching the whole document:
- observe only a container that can actually contain table fields, or
- skip attaching it entirely when no
.acf-table-rootexists on the page, or - prefer ACF’s own
append/readyactions over a MutationObserver, which is how ACF
expects add-ons to learn about new fields, and - optionally offer a constant to opt out, in the spirit of the existing
ACF_TABLEFIELD_FILTER_POSTMETA.
Happy to test a patch against the above setup.
You must be logged in to reply to this topic.