From 2e703f7aaac212f72fc8ea1e9fd483abf5304c8e Mon Sep 17 00:00:00 2001 From: Masen Furer Date: Thu, 24 Oct 2024 14:34:23 -0700 Subject: [PATCH] Fix 'enter_key_submit=True' on 'rx.text_area' by carrying custom_code on debounce (#4142) * debounce: handle custom code from child component Include _get_all_hooks when rendering the child element, instead of just internal hooks. * textarea: handle special behaviors during `create` Move special behavior handling to `create` classmethod to allow carrying of added props when wrapped in debounce, which does not call `_render` on the child component. --- reflex/components/core/debounce.py | 6 ++- reflex/components/el/elements/forms.py | 58 +++++++++++++++---------- reflex/components/el/elements/forms.pyi | 11 +++-- 3 files changed, 48 insertions(+), 27 deletions(-) diff --git a/reflex/components/core/debounce.py b/reflex/components/core/debounce.py index 07ad1d69e..86efb7dcd 100644 --- a/reflex/components/core/debounce.py +++ b/reflex/components/core/debounce.py @@ -118,7 +118,7 @@ class DebounceInput(Component): _var_type=Type[Component], _var_data=VarData( imports=child._get_imports(), - hooks=child._get_hooks_internal(), + hooks=child._get_all_hooks(), ), ), ) @@ -128,6 +128,10 @@ class DebounceInput(Component): component.event_triggers.update(child.event_triggers) component.children = child.children component._rename_props = child._rename_props + outer_get_all_custom_code = component._get_all_custom_code + component._get_all_custom_code = lambda: outer_get_all_custom_code().union( + child._get_all_custom_code() + ) return component def _render(self): diff --git a/reflex/components/el/elements/forms.py b/reflex/components/el/elements/forms.py index a343991d5..d1c77c555 100644 --- a/reflex/components/el/elements/forms.py +++ b/reflex/components/el/elements/forms.py @@ -615,6 +615,42 @@ class Textarea(BaseHTML): # Fired when a key is released on_key_up: EventHandler[key_event] + @classmethod + def create(cls, *children, **props): + """Create a textarea component. + + Args: + *children: The children of the textarea. + **props: The properties of the textarea. + + Returns: + The textarea component. + + Raises: + ValueError: when `enter_key_submit` is combined with `on_key_down`. + """ + enter_key_submit = props.get("enter_key_submit") + auto_height = props.get("auto_height") + custom_attrs = props.setdefault("custom_attrs", {}) + + if enter_key_submit is not None: + enter_key_submit = Var.create(enter_key_submit) + if "on_key_down" in props: + raise ValueError( + "Cannot combine `enter_key_submit` with `on_key_down`.", + ) + custom_attrs["on_key_down"] = Var( + _js_expr=f"(e) => enterKeySubmitOnKeyDown(e, {str(enter_key_submit)})", + _var_data=VarData.merge(enter_key_submit._get_all_var_data()), + ) + if auto_height is not None: + auto_height = Var.create(auto_height) + custom_attrs["on_input"] = Var( + _js_expr=f"(e) => autoHeightOnInput(e, {str(auto_height)})", + _var_data=VarData.merge(auto_height._get_all_var_data()), + ) + return super().create(*children, **props) + def _exclude_props(self) -> list[str]: return super()._exclude_props() + [ "auto_height", @@ -634,28 +670,6 @@ class Textarea(BaseHTML): custom_code.add(ENTER_KEY_SUBMIT_JS) return custom_code - def _render(self) -> Tag: - tag = super()._render() - if self.enter_key_submit is not None: - if "on_key_down" in self.event_triggers: - raise ValueError( - "Cannot combine `enter_key_submit` with `on_key_down`.", - ) - tag.add_props( - on_key_down=Var( - _js_expr=f"(e) => enterKeySubmitOnKeyDown(e, {str(self.enter_key_submit)})", - _var_data=VarData.merge(self.enter_key_submit._get_all_var_data()), - ) - ) - if self.auto_height is not None: - tag.add_props( - on_input=Var( - _js_expr=f"(e) => autoHeightOnInput(e, {str(self.auto_height)})", - _var_data=VarData.merge(self.auto_height._get_all_var_data()), - ) - ) - return tag - button = Button.create fieldset = Fieldset.create diff --git a/reflex/components/el/elements/forms.pyi b/reflex/components/el/elements/forms.pyi index 135291213..2f889bc38 100644 --- a/reflex/components/el/elements/forms.pyi +++ b/reflex/components/el/elements/forms.pyi @@ -1376,10 +1376,10 @@ class Textarea(BaseHTML): on_unmount: Optional[EventType[[]]] = None, **props, ) -> "Textarea": - """Create the component. + """Create a textarea component. Args: - *children: The children of the component. + *children: The children of the textarea. auto_complete: Whether the form control should have autocomplete enabled auto_focus: Automatically focuses the textarea when the page loads auto_height: Automatically fit the content height to the text (use min-height with this prop) @@ -1419,10 +1419,13 @@ class Textarea(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 textarea. Returns: - The component. + The textarea component. + + Raises: + ValueError: when `enter_key_submit` is combined with `on_key_down`. """ ...