Skip to content

fix(DFV): surface field id on loader div so label for resolves before hydration - #7575

Open
faisalahammad wants to merge 3 commits into
pods-framework:release/3.4.0from
faisalahammad:fix/7278-dfv-label-for-target-id-on-loader
Open

fix(DFV): surface field id on loader div so label for resolves before hydration#7575
faisalahammad wants to merge 3 commits into
pods-framework:release/3.4.0from
faisalahammad:fix/7278-dfv-label-for-target-id-on-loader

Conversation

@faisalahammad

@faisalahammad faisalahammad commented Jul 26, 2026

Copy link
Copy Markdown
Contributor

Description

DFV fields (file, avatar, code, boolean, wysiwyg, etc.) currently render only a loader <div> server-side. The actual <input id="..."> only appears after React hydrates, which means the sibling <label for="pods-form-ui-{name}"> points at an id that does not exist in the SSR markup. This breaks browser autofill, accessibility tools, and Lighthouse form-label checks.

The id formula was already in PodsForm::merge_attributes() and forwarded to React via build_dfv_field_data()['htmlAttr']['id']. This change emits that same id on the loader <div> itself, so the label resolves before hydration and React behavior is unchanged (the inner control still reads the same id from htmlAttr).

Related GitHub issue(s)

Fixes #7278

Testing instructions

  1. Activate Pods on a WordPress install with a Pod that exposes a DFV field type (file, avatar, wysiwyg, or code).
  2. Open the create or edit screen for an item in that Pod.
  3. View source (do not run JS yet). Confirm:
    • The loader markup now includes id="pods-form-ui-{field-name}" on the <div class="pods-form-ui-field pods-dfv-field pods-dfv-field--unloaded">.
    • The matching sibling <label for="pods-form-ui-{field-name}"> resolves to that same id byte-for-byte.
  4. Load the page fully with JS enabled. Inspect the DOM after hydration and confirm the inner React-rendered control uses the same id without duplicate-id warnings in the console.
  5. Place two Pods Forms on the same page with the same field name. Confirm the -2 / -3 suffix keeps each label + loader id pair consistent.
  6. Run Lighthouse or axe on the edit screen. Confirm the "form element does not have a label" / "label without control" warning no longer fires for the field above.
  7. Smoke test a non-DFV field (text, paragraph) to confirm its render path is untouched.

Screenshots / screencast

Not applicable.

Changelog text for these changes

Bug: DFV field labels no longer dangle — the loader element now carries the id the <label for> already points to, so browser autofill and accessibility checks resolve correctly. #7278 (@faisalahammad)

PR checklist

  • I have tested my own code to confirm it works as I intended.
  • My code follows the WordPress Coding Standards.
  • My code follows the WordPress Inline Documentation Standards.
  • My code includes automated tests for PHP and/or JS (if applicable).

DFV fields emit only a loader <div> server-side; the actual <input>
appears after React hydrates. The sibling <label for=...> therefore
points at an id that does not exist in the SSR markup, which breaks
browser autofill and accessibility tools.

The id is already computed in PodsForm::merge_attributes() and shipped
to React via build_dfv_field_data()['htmlAttr']['id']. Re-use that same
value on the loader <div> so the label resolves immediately and React
hydration stays unchanged.

Fixes pods-framework#7278.
@what-the-diff

what-the-diff Bot commented Jul 26, 2026

Copy link
Copy Markdown

PR Summary

  • Improved Website Components Identification:
    The team has updated certain parts of the website (i.e., a type of web component known as 'div' elements). They've given these elements a unique identifier (also known as an 'ID attribute'), but only when there's corresponding information available in a particular dataset (i.e., $dfv_field_data). This improvement will enable the system to correctly identify and work with related elements on the webpage (in this case, 'label' elements) before it becomes interactive, which will enhance the user experience on the site.

@faisalahammad
faisalahammad changed the base branch from main to release/3.4.0 August 18, 2026 11:36
@faisalahammad

Copy link
Copy Markdown
Contributor Author

AI disclosure: this PR was written with Claude Opus 5 assistance, reviewed and tested by me.

faisalahammad and others added 2 commits August 19, 2026 23:43
…r div

The previous approach put the field id on the .pods-dfv-field loader div.
DFV renders through ReactDOM.createPortal() into that same div (core/app.js),
and the field controls already apply htmlAttr.id themselves, so the div and
the control ended up sharing one id. document.getElementById() returns the
first match in document order -- the wrapper div -- which broke
wysiwyg/tinymce.js destroyEditor()/reInit(), and a <div> is not a labelable
element so <label for> could not address it anyway.

The loader markup is restored, and the real gap is closed instead: the
react-select based pick controls never received an id at all, so
<label for="pods-form-ui-{name}"> had nothing to resolve to. FullSelect now
accepts inputId and forwards it to react-select, which applies it to its
internal <input>.

Refs pods-framework#7278
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.

Pods triggers error on CPT "Incorrect use of <label for=FORM_ELEMENT>"

1 participant