fix(forms): take a form control's name from its rx.form.field
All Submissions:
- Have you followed the guidelines stated in CONTRIBUTING.md file?
- Have you checked to ensure there aren't any other open Pull Requests for the desired changed?
Type of change
- Bug fix (non-breaking change which fixes an issue)
- This change requires a documentation update
Description
Radix passes an rx.form.field's name to the control rendered by its rx.form.control, so an rx.input there submits under the field's name even without a name of its own. The static form walk in forms.py only read each control's own name, so compiling a form like the one in the low-level form docs:
rx.form.root(
rx.form.field(
rx.form.control(rx.input(id="email", type="email"), as_child=True),
name="email",
),
on_submit=State.handle_submit,
)
warned that the control with id 'email' is submitted by its id and will stop being submitted in 0.11, and a TypedDict submit handler raised a "Form field mismatch" error for the field the control fills.
The walk now carries the name an enclosing form field control passes on: its own name, or else that of the enclosing form field. A control's own name still wins, matching Radix's slot merge order. An rx.form.control with no child renders an input itself, so it now counts as a form control; with a child it names that child, including a debounced input. A control that sits in a named field but outside rx.form.control, or in an unnamed field, still warns, since Radix does not name it.
Components opt into these roles with the new _is_form_field and _is_form_field_control class flags on Component, next to the existing _is_form_control, set on rx.form.field and rx.form.control. Core reads them with getattr, so no sibling floors change.
Changes To Core Features:
- Have you added an explanation of what your changes do and why you'd like us to include them?
- Have you written new tests for your core changes, as applicable?
- Have you successfully ran tests with your changes locally?
Regression tests in tests/units/components/forms/test_form.py cover the no-warning cases (slot child, bare control, debounced child, control-level name), the still-warning cases, and TypedDict validation with static, dynamic, and mismatched field names. Docs for both form pages note the inherited name, and news fragments are added for reflex-base, reflex-components-core, and reflex-components-radix.
Generated by Claude Code