[ENG-4153]Use empty string for None values in rx.input
and rx.el.input
(#4521)
* Use empty string for None values in `rx.input` and `rx.el.input` * fix tests * fix pyi scripts * use nullish coalescing operator * fix unit tests * use ternary operator so old browsers and dynamic components tests pass * address comment on doing this only for optionals * Fix tests * pyright! * fix comments
This commit is contained in:
parent
d5d41a0d9e
commit
7ca50c62e2
@ -18,6 +18,7 @@ from reflex.event import (
|
|||||||
prevent_default,
|
prevent_default,
|
||||||
)
|
)
|
||||||
from reflex.utils.imports import ImportDict
|
from reflex.utils.imports import ImportDict
|
||||||
|
from reflex.utils.types import is_optional
|
||||||
from reflex.vars import VarData
|
from reflex.vars import VarData
|
||||||
from reflex.vars.base import LiteralVar, Var
|
from reflex.vars.base import LiteralVar, Var
|
||||||
|
|
||||||
@ -382,6 +383,33 @@ class Input(BaseHTML):
|
|||||||
# Fired when a key is released
|
# Fired when a key is released
|
||||||
on_key_up: EventHandler[key_event]
|
on_key_up: EventHandler[key_event]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def create(cls, *children, **props):
|
||||||
|
"""Create an Input component.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
*children: The children of the component.
|
||||||
|
**props: The properties of the component.
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
The component.
|
||||||
|
"""
|
||||||
|
from reflex.vars.number import ternary_operation
|
||||||
|
|
||||||
|
value = props.get("value")
|
||||||
|
|
||||||
|
# React expects an empty string(instead of null) for controlled inputs.
|
||||||
|
if value is not None and is_optional(
|
||||||
|
(value_var := Var.create(value))._var_type
|
||||||
|
):
|
||||||
|
props["value"] = ternary_operation(
|
||||||
|
(value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues]
|
||||||
|
& (value_var != Var(_js_expr="undefined")),
|
||||||
|
value,
|
||||||
|
Var.create(""),
|
||||||
|
)
|
||||||
|
return super().create(*children, **props)
|
||||||
|
|
||||||
|
|
||||||
class Label(BaseHTML):
|
class Label(BaseHTML):
|
||||||
"""Display the label element."""
|
"""Display the label element."""
|
||||||
|
@ -512,7 +512,7 @@ class Input(BaseHTML):
|
|||||||
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
|
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
|
||||||
**props,
|
**props,
|
||||||
) -> "Input":
|
) -> "Input":
|
||||||
"""Create the component.
|
"""Create an Input component.
|
||||||
|
|
||||||
Args:
|
Args:
|
||||||
*children: The children of the component.
|
*children: The children of the component.
|
||||||
@ -576,7 +576,7 @@ class Input(BaseHTML):
|
|||||||
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.
|
**props: The properties of the component.
|
||||||
|
|
||||||
Returns:
|
Returns:
|
||||||
The component.
|
The component.
|
||||||
|
@ -9,7 +9,9 @@ from reflex.components.core.breakpoints import Responsive
|
|||||||
from reflex.components.core.debounce import DebounceInput
|
from reflex.components.core.debounce import DebounceInput
|
||||||
from reflex.components.el import elements
|
from reflex.components.el import elements
|
||||||
from reflex.event import EventHandler, input_event, key_event
|
from reflex.event import EventHandler, input_event, key_event
|
||||||
|
from reflex.utils.types import is_optional
|
||||||
from reflex.vars.base import Var
|
from reflex.vars.base import Var
|
||||||
|
from reflex.vars.number import ternary_operation
|
||||||
|
|
||||||
from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
|
from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent
|
||||||
|
|
||||||
@ -96,6 +98,19 @@ class TextFieldRoot(elements.Div, RadixThemesComponent):
|
|||||||
Returns:
|
Returns:
|
||||||
The component.
|
The component.
|
||||||
"""
|
"""
|
||||||
|
value = props.get("value")
|
||||||
|
|
||||||
|
# React expects an empty string(instead of null) for controlled inputs.
|
||||||
|
if value is not None and is_optional(
|
||||||
|
(value_var := Var.create(value))._var_type
|
||||||
|
):
|
||||||
|
props["value"] = ternary_operation(
|
||||||
|
(value_var != Var.create(None)) # pyright: ignore [reportGeneralTypeIssues]
|
||||||
|
& (value_var != Var(_js_expr="undefined")),
|
||||||
|
value,
|
||||||
|
Var.create(""),
|
||||||
|
)
|
||||||
|
|
||||||
component = super().create(*children, **props)
|
component = super().create(*children, **props)
|
||||||
if props.get("value") is not None and props.get("on_change") is not None:
|
if props.get("value") is not None and props.get("on_change") is not None:
|
||||||
# create a debounced input if the user requests full control to avoid typing jank
|
# create a debounced input if the user requests full control to avoid typing jank
|
||||||
|
Loading…
Reference in New Issue
Block a user