feat(forms): render any native form control under rx.form.control

Merged
MA
3d ago
+219-12

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

  • New feature (non-breaking change which adds functionality)
  • This change requires a documentation update

Description

Stacked on reflex-dev/reflex#7724, which teaches form compilation that a control rendered by rx.form.control takes its rx.form.field's name.

rx.form.control only accepted rx.input and rx.debounce_input as its child, so a textarea or a low-level input, textarea or select could not take a form field's name and validation messages:

TypeError: Only Radix TextFieldRoot and DebounceInput are allowed as children of FormControl

Upstream Radix Form.Control composes with any native form control, and with nothing else: the Radix docs state that it cannot yet be composed with the other form primitives such as Checkbox and Select.

  • FormControl.create now accepts every component backed by a native input, select or textarea, which covers rx.input, rx.text_area, rx.debounce_input, rx.el.input, rx.el.textarea and rx.el.select, and keeps rejecting the rest with a message that says to give those controls a name and place them under the root or field instead.
  • A child is only rendered as the control with asChild, so as_child is set whenever a child is given, even over an explicit as_child=False; without it Radix renders an <input> with children, which React refuses and the page fails to render.
  • The low-level form docs list what a Form Control renders and where the unsupported controls go.

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?

Unit tests cover acceptance of each native control and the exact rejection message. The new Playwright test tests/integration/tests_playwright/test_radix_form_control.py runs a form with one field per accepted control, including a fully controlled input that compiles to DebounceInput, and checks that each control carries its field's name and the id its label points to, that a required textarea blocks submission and shows its rx.form.message, and that the submitted payload holds every value, with no page errors.


Generated by Claude Code