Forráskód Böngészése

Clean up Radix Form component (#2423)

* form pr

* cleanup

* pyi
Martin Xu 1 éve
szülő
commit
84858854ae

+ 32 - 3
reflex/components/radix/primitives/form.py

@@ -8,6 +8,7 @@ from typing import Any, Dict, Iterator, Literal
 from jinja2 import Environment
 from jinja2 import Environment
 
 
 from reflex.components.component import Component
 from reflex.components.component import Component
+from reflex.components.radix.themes.components.textfield import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
 from reflex.constants.base import Dirs
 from reflex.constants.event import EventTriggers
 from reflex.constants.event import EventTriggers
@@ -52,7 +53,7 @@ class FormRoot(FormComponent):
     # If true, the form will be cleared after submit.
     # If true, the form will be cleared after submit.
     reset_on_submit: Var[bool] = False  # type: ignore
     reset_on_submit: Var[bool] = False  # type: ignore
 
 
-    # The name used to make this form's submit handler function unique
+    # The name used to make this form's submit handler function unique.
     handle_submit_unique_name: Var[str]
     handle_submit_unique_name: Var[str]
 
 
     def get_event_triggers(self) -> Dict[str, Any]:
     def get_event_triggers(self) -> Dict[str, Any]:
@@ -64,7 +65,7 @@ class FormRoot(FormComponent):
         return {
         return {
             **super().get_event_triggers(),
             **super().get_event_triggers(),
             EventTriggers.ON_SUBMIT: lambda e0: [FORM_DATA],
             EventTriggers.ON_SUBMIT: lambda e0: [FORM_DATA],
-            "on_clear_server_errors": lambda: [],
+            EventTriggers.ON_CLEAR_SERVER_ERRORS: lambda: [],
         }
         }
 
 
     @classmethod
     @classmethod
@@ -171,8 +172,10 @@ class FormField(FormComponent):
 
 
     alias = "RadixFormField"
     alias = "RadixFormField"
 
 
+    # The name of the form field, that is passed down to the control and used to match with validation messages.
     name: Var[str]
     name: Var[str]
 
 
+    # Flag to mark the form field as invalid, for server side validation.
     server_invalid: Var[bool]
     server_invalid: Var[bool]
 
 
     def _apply_theme(self, theme: Component | None):
     def _apply_theme(self, theme: Component | None):
@@ -206,6 +209,32 @@ class FormControl(FormComponent):
 
 
     alias = "RadixFormControl"
     alias = "RadixFormControl"
 
 
+    @classmethod
+    def create(cls, *children, **props):
+        """Create a Form Control component.
+
+        Args:
+            *children: The children of the form.
+            **props: The properties of the form.
+
+        Raises:
+            ValueError: If the number of children is greater than 1.
+            TypeError: If a child exists but it is not a TextFieldInput.
+
+        Returns:
+            The form control component.
+        """
+        if len(children) > 1:
+            raise ValueError(
+                f"FormControl can only have at most one child, got {len(children)} children"
+            )
+        for child in children:
+            if not isinstance(child, TextFieldInput):
+                raise TypeError(
+                    "Only Radix TextFieldInput is allowed as child of FormControl"
+                )
+        return super().create(*children, **props)
+
 
 
 LiteralMatcher = Literal[
 LiteralMatcher = Literal[
     "badInput",
     "badInput",
@@ -235,7 +264,7 @@ class FormMessage(FormComponent):
     match: Var[LiteralMatcher]
     match: Var[LiteralMatcher]
 
 
     # Forces the message to be shown. This is useful when using server-side validation.
     # Forces the message to be shown. This is useful when using server-side validation.
-    forceMatch: Var[bool]
+    force_match: Var[bool]
 
 
     def _apply_theme(self, theme: Component | None):
     def _apply_theme(self, theme: Component | None):
         return {
         return {

+ 14 - 10
reflex/components/radix/primitives/form.pyi

@@ -11,6 +11,7 @@ from hashlib import md5
 from typing import Any, Dict, Iterator, Literal
 from typing import Any, Dict, Iterator, Literal
 from jinja2 import Environment
 from jinja2 import Environment
 from reflex.components.component import Component
 from reflex.components.component import Component
+from reflex.components.radix.themes.components.textfield import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
 from reflex.constants.base import Dirs
 from reflex.constants.event import EventTriggers
 from reflex.constants.event import EventTriggers
@@ -180,7 +181,7 @@ class FormRoot(FormComponent):
         Args:
         Args:
             *children: The children of the form.
             *children: The children of the form.
             reset_on_submit: If true, the form will be cleared after submit.
             reset_on_submit: If true, the form will be cleared after submit.
-            handle_submit_unique_name: The name used to make this form's submit handler function unique
+            handle_submit_unique_name: The name used to make this form's submit handler function unique.
             as_child: Change the default rendered element for the one passed as a child.
             as_child: Change the default rendered element for the one passed as a child.
             style: The style of the component.
             style: The style of the component.
             key: A unique key for the component.
             key: A unique key for the component.
@@ -261,6 +262,8 @@ class FormField(FormComponent):
 
 
         Args:
         Args:
             *children: The children of the component.
             *children: The children of the component.
+            name: The name of the form field, that is passed down to the control and used to match with validation messages.
+            server_invalid: Flag to mark the form field as invalid, for server side validation.
             as_child: Change the default rendered element for the one passed as a child.
             as_child: Change the default rendered element for the one passed as a child.
             style: The style of the component.
             style: The style of the component.
             key: A unique key for the component.
             key: A unique key for the component.
@@ -419,10 +422,10 @@ class FormControl(FormComponent):
         ] = None,
         ] = None,
         **props
         **props
     ) -> "FormControl":
     ) -> "FormControl":
-        """Create the component.
+        """Create a Form Control component.
 
 
         Args:
         Args:
-            *children: The children of the component.
+            *children: The children of the form.
             as_child: Change the default rendered element for the one passed as a child.
             as_child: Change the default rendered element for the one passed as a child.
             style: The style of the component.
             style: The style of the component.
             key: A unique key for the component.
             key: A unique key for the component.
@@ -430,13 +433,14 @@ class FormControl(FormComponent):
             class_name: The class name for the component.
             class_name: The class name for the component.
             autofocus: Whether the component should take the focus once the page is loaded
             autofocus: Whether the component should take the focus once the page is loaded
             custom_attrs: custom attribute
             custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
+            **props: The properties of the form.
 
 
         Raises:
         Raises:
-            TypeError: If an invalid child is passed.
+            ValueError: If the number of children is greater than 1.
+            TypeError: If a child exists but it is not a TextFieldInput.
+
+        Returns:
+            The form control component.
         """
         """
         ...
         ...
 
 
@@ -490,7 +494,7 @@ class FormMessage(FormComponent):
                 ],
                 ],
             ]
             ]
         ] = None,
         ] = None,
-        forceMatch: Optional[Union[Var[bool], bool]] = None,
+        force_match: Optional[Union[Var[bool], bool]] = None,
         as_child: Optional[Union[Var[bool], bool]] = None,
         as_child: Optional[Union[Var[bool], bool]] = None,
         style: Optional[Style] = None,
         style: Optional[Style] = None,
         key: Optional[Any] = None,
         key: Optional[Any] = None,
@@ -551,7 +555,7 @@ class FormMessage(FormComponent):
             *children: The children of the component.
             *children: The children of the component.
             name: Used to target a specific field by name when rendering outside of a Field part.
             name: Used to target a specific field by name when rendering outside of a Field part.
             match: Used to indicate on which condition the message should be visible.
             match: Used to indicate on which condition the message should be visible.
-            forceMatch: Forces the message to be shown. This is useful when using server-side validation.
+            force_match: Forces the message to be shown. This is useful when using server-side validation.
             as_child: Change the default rendered element for the one passed as a child.
             as_child: Change the default rendered element for the one passed as a child.
             style: The style of the component.
             style: The style of the component.
             key: A unique key for the component.
             key: A unique key for the component.

+ 1 - 0
reflex/constants/event.py

@@ -84,3 +84,4 @@ class EventTriggers(SimpleNamespace):
     ON_SUBMIT = "on_submit"
     ON_SUBMIT = "on_submit"
     ON_MOUNT = "on_mount"
     ON_MOUNT = "on_mount"
     ON_UNMOUNT = "on_unmount"
     ON_UNMOUNT = "on_unmount"
+    ON_CLEAR_SERVER_ERRORS = "on_clear_server_errors"