reflex/docs/library/forms/form.md
2024-02-26 17:18:28 +01:00

229 lines
7.1 KiB
Markdown

---
components:
- rx.radix.form
- rx.radix.form.root
- rx.radix.form.field
- rx.radix.form.control
- rx.radix.form.label
- rx.radix.form.message
- rx.radix.form.submit
FormRoot: |
lambda **props: rx.form.root(
rx.form.field(
rx.flex(
rx.form.label("Email"),
rx.form.control(
rx.input.input(
placeholder="Email Address",
# type attribute is required for "typeMismatch" validation
type="email",
),
as_child=True,
),
rx.form.message("Please enter a valid email"),
rx.form.submit(
rx.button("Submit"),
as_child=True,
),
direction="column",
spacing="2",
align="stretch",
),
name="email",
),
**props,
)
FormField: |
lambda **props: rx.form.root(
rx.form.field(
rx.flex(
rx.form.label("Email"),
rx.form.control(
rx.input.input(
placeholder="Email Address",
# type attribute is required for "typeMismatch" validation
type="email",
),
as_child=True,
),
rx.form.message("Please enter a valid email", match="typeMismatch"),
rx.form.submit(
rx.button("Submit"),
as_child=True,
),
direction="column",
spacing="2",
align="stretch",
),
**props,
),
reset_on_submit=True,
)
FormLabel: |
lambda **props: rx.form.root(
rx.form.field(
rx.flex(
rx.form.label("Email", **props,),
rx.form.control(
rx.input.input(
placeholder="Email Address",
# type attribute is required for "typeMismatch" validation
type="email",
),
as_child=True,
),
rx.form.message("Please enter a valid email", match="typeMismatch"),
rx.form.submit(
rx.button("Submit"),
as_child=True,
),
direction="column",
spacing="2",
align="stretch",
),
),
reset_on_submit=True,
)
FormMessage: |
lambda **props: rx.form.root(
rx.form.field(
rx.flex(
rx.form.label("Email"),
rx.form.control(
rx.input.input(
placeholder="Email Address",
# type attribute is required for "typeMismatch" validation
type="email",
),
as_child=True,
),
rx.form.message("Please enter a valid email", **props,),
rx.form.submit(
rx.button("Submit"),
as_child=True,
),
direction="column",
spacing="2",
align="stretch",
),
name="email",
),
on_submit=lambda form_data: rx.window_alert(form_data.to_string()),
reset_on_submit=True,
)
---
```python exec
import reflex as rx
```
# Form
Forms are used to collect user input. The `rx.form` component is used to group inputs and submit them together.
The form component's children can be form controls such as `rx.input`, `rx.checkbox`, `rx.slider`, `rx.textarea`, `rx.radio_group`, `rx.select` or `rx.switch`. The controls should have a `name` attribute that is used to identify the control in the form data. The `on_submit` event trigger submits the form data as a dictionary to the `handle_submit` event handler.
The form is submitted when the user clicks the submit button or presses enter on the form controls.
```python demo exec
class FormState(rx.State):
form_data: dict = {}
def handle_submit(self, form_data: dict):
"""Handle the form submit."""
self.form_data = form_data
def form_example():
return rx.vstack(
rx.form(
rx.vstack(
rx.input(placeholder="First Name", name="first_name"),
rx.input(placeholder="Last Name", name="last_name"),
rx.hstack(
rx.checkbox("Checked", name="check"),
rx.switch("Switched", name="switch"),
),
rx.button("Submit", type="submit"),
),
on_submit=FormState.handle_submit,
reset_on_submit=True,
),
rx.divider(),
rx.heading("Results"),
rx.text(FormState.form_data.to_string()),
)
```
```md alert warning
# When using the form you must include a button or input with `type='submit'`.
```
## Dynamic Forms
Forms can be dynamically created by iterating through state vars using `rx.foreach`.
This example allows the user to add new fields to the form prior to submit, and all
fields will be included in the form data passed to the `handle_submit` function.
```python demo exec
class DynamicFormState(rx.State):
form_data: dict = {}
form_fields: list[str] = ["first_name", "last_name", "email"]
@rx.cached_var
def form_field_placeholders(self) -> list[str]:
return [
" ".join(w.capitalize() for w in field.split("_"))
for field in self.form_fields
]
def add_field(self, form_data: dict):
new_field = form_data.get("new_field")
if not new_field:
return
field_name = new_field.strip().lower().replace(" ", "_")
self.form_fields.append(field_name)
def handle_submit(self, form_data: dict):
self.form_data = form_data
def dynamic_form():
return rx.vstack(
rx.form(
rx.vstack(
rx.foreach(
DynamicFormState.form_fields,
lambda field, idx: rx.input(
placeholder=DynamicFormState.form_field_placeholders[idx],
name=field,
),
),
rx.button("Submit", type="submit"),
),
on_submit=DynamicFormState.handle_submit,
reset_on_submit=True,
),
rx.form(
rx.hstack(
rx.input(placeholder="New Field", name="new_field"),
rx.button("+", type="submit"),
),
on_submit=DynamicFormState.add_field,
reset_on_submit=True,
),
rx.divider(),
rx.heading("Results"),
rx.text(DynamicFormState.form_data.to_string()),
)
```