Skip to content

Commit

Permalink
[ENG-4153]Use empty string for None values in rx.input and `rx.el.i…
Browse files Browse the repository at this point in the history
…nput` (#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
  • Loading branch information
ElijahAhianyo authored Dec 12, 2024
1 parent d5d41a0 commit 7ca50c6
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 2 deletions.
28 changes: 28 additions & 0 deletions reflex/components/el/elements/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
prevent_default,
)
from reflex.utils.imports import ImportDict
from reflex.utils.types import is_optional
from reflex.vars import VarData
from reflex.vars.base import LiteralVar, Var

Expand Down Expand Up @@ -382,6 +383,33 @@ class Input(BaseHTML):
# Fired when a key is released
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):
"""Display the label element."""
Expand Down
4 changes: 2 additions & 2 deletions reflex/components/el/elements/forms.pyi
Original file line number Diff line number Diff line change
Expand Up @@ -512,7 +512,7 @@ class Input(BaseHTML):
on_unmount: Optional[EventType[[], BASE_STATE]] = None,
**props,
) -> "Input":
"""Create the component.
"""Create an Input component.
Args:
*children: The children of the component.
Expand Down Expand Up @@ -576,7 +576,7 @@ class Input(BaseHTML):
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.
**props: The properties of the component.
Returns:
The component.
Expand Down
15 changes: 15 additions & 0 deletions reflex/components/radix/themes/components/text_field.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
from reflex.components.core.debounce import DebounceInput
from reflex.components.el import elements
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.number import ternary_operation

from ..base import LiteralAccentColor, LiteralRadius, RadixThemesComponent

Expand Down Expand Up @@ -96,6 +98,19 @@ def create(cls, *children, **props) -> Component:
Returns:
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)
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
Expand Down

0 comments on commit 7ca50c6

Please sign in to comment.