Browse Source

Clean up Radix Form component (#2423)

* form pr

* cleanup

* pyi
Martin Xu 1 year ago
parent
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 reflex.components.component import Component
+from reflex.components.radix.themes.components.textfield import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
 from reflex.constants.event import EventTriggers
@@ -52,7 +53,7 @@ class FormRoot(FormComponent):
     # If true, the form will be cleared after submit.
     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]
 
     def get_event_triggers(self) -> Dict[str, Any]:
@@ -64,7 +65,7 @@ class FormRoot(FormComponent):
         return {
             **super().get_event_triggers(),
             EventTriggers.ON_SUBMIT: lambda e0: [FORM_DATA],
-            "on_clear_server_errors": lambda: [],
+            EventTriggers.ON_CLEAR_SERVER_ERRORS: lambda: [],
         }
 
     @classmethod
@@ -171,8 +172,10 @@ class FormField(FormComponent):
 
     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]
 
+    # Flag to mark the form field as invalid, for server side validation.
     server_invalid: Var[bool]
 
     def _apply_theme(self, theme: Component | None):
@@ -206,6 +209,32 @@ class FormControl(FormComponent):
 
     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[
     "badInput",
@@ -235,7 +264,7 @@ class FormMessage(FormComponent):
     match: Var[LiteralMatcher]
 
     # 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):
         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 jinja2 import Environment
 from reflex.components.component import Component
+from reflex.components.radix.themes.components.textfield import TextFieldInput
 from reflex.components.tags.tag import Tag
 from reflex.constants.base import Dirs
 from reflex.constants.event import EventTriggers
@@ -180,7 +181,7 @@ class FormRoot(FormComponent):
         Args:
             *children: The children of the form.
             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.
             style: The style of the component.
             key: A unique key for the component.
@@ -261,6 +262,8 @@ class FormField(FormComponent):
 
         Args:
             *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.
             style: The style of the component.
             key: A unique key for the component.
@@ -419,10 +422,10 @@ class FormControl(FormComponent):
         ] = None,
         **props
     ) -> "FormControl":
-        """Create the component.
+        """Create a Form Control component.
 
         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.
             style: The style of the component.
             key: A unique key for the component.
@@ -430,13 +433,14 @@ class FormControl(FormComponent):
             class_name: The class name for the component.
             autofocus: Whether the component should take the focus once the page is loaded
             custom_attrs: custom attribute
-            **props: The props of the component.
-
-        Returns:
-            The component.
+            **props: The properties of the form.
 
         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,
-        forceMatch: Optional[Union[Var[bool], bool]] = None,
+        force_match: Optional[Union[Var[bool], bool]] = None,
         as_child: Optional[Union[Var[bool], bool]] = None,
         style: Optional[Style] = None,
         key: Optional[Any] = None,
@@ -551,7 +555,7 @@ class FormMessage(FormComponent):
             *children: The children of the component.
             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.
-            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.
             style: The style of 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_MOUNT = "on_mount"
     ON_UNMOUNT = "on_unmount"
+    ON_CLEAR_SERVER_ERRORS = "on_clear_server_errors"