Skip to content

Commit 4bc26bf

Browse files
masenfadhami3310
authored andcommitted
Support event_actions in Form on_submit (#4912)
1 parent 667ae82 commit 4bc26bf

File tree

3 files changed

+54
-3
lines changed

3 files changed

+54
-3
lines changed

reflex/components/el/elements/forms.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
ev.preventDefault()
3333
const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}};
3434
35-
({{ on_submit_event_chain }}());
35+
({{ on_submit_event_chain }}(ev));
3636
3737
if ({{ reset_on_submit }}) {
3838
$form.reset()

reflex/components/el/elements/forms.pyi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ from .base import BaseHTML
1717

1818
FORM_DATA = Var(_js_expr="form_data")
1919
HANDLE_SUBMIT_JS_JINJA2 = Environment().from_string(
20-
"\n const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {\n const $form = ev.target\n ev.preventDefault()\n const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}};\n\n ({{ on_submit_event_chain }}());\n\n if ({{ reset_on_submit }}) {\n $form.reset()\n }\n })\n "
20+
"\n const handleSubmit_{{ handle_submit_unique_name }} = useCallback((ev) => {\n const $form = ev.target\n ev.preventDefault()\n const {{ form_data }} = {...Object.fromEntries(new FormData($form).entries()), ...{{ field_ref_mapping }}};\n\n ({{ on_submit_event_chain }}(ev));\n\n if ({{ reset_on_submit }}) {\n $form.reset()\n }\n })\n "
2121
)
2222
ButtonType = Literal["submit", "reset", "button"]
2323

tests/integration/test_event_actions.py

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,17 @@
88

99
import pytest
1010
from selenium.webdriver.common.by import By
11+
from selenium.webdriver.common.keys import Keys
12+
from selenium.webdriver.support import expected_conditions as EC
13+
from selenium.webdriver.support.wait import WebDriverWait
1114

1215
from reflex.testing import AppHarness, WebDriver
1316

1417

1518
def TestEventAction():
1619
"""App for testing event_actions."""
20+
from typing import Any
21+
1722
import reflex as rx
1823

1924
class EventActionState(rx.State):
@@ -32,6 +37,10 @@ def on_click_throttle(self):
3237
def on_click_debounce(self):
3338
self.order.append("on_click_debounce")
3439

40+
@rx.event
41+
def on_submit(self, form_data: dict[str, Any]):
42+
self.order.append("on_submit")
43+
3544
class EventFiringComponent(rx.Component):
3645
"""A component that fires onClick event without passing DOM event."""
3746

@@ -152,10 +161,26 @@ def index():
152161
),
153162
),
154163
on_click=EventActionState.on_click("outer"), # pyright: ignore [reportCallIssue]
164+
), rx.form(
165+
rx.dialog.root(
166+
rx.dialog.trigger(
167+
rx.button("Open Dialog", type="button", id="btn-dialog"),
168+
on_click=rx.stop_propagation, # pyright: ignore [reportArgumentType]
169+
),
170+
rx.dialog.content(
171+
rx.dialog.close(
172+
rx.form(
173+
rx.button("Submit", id="btn-submit"),
174+
on_submit=EventActionState.on_submit.stop_propagation, # pyright: ignore [reportCallIssue]
175+
),
176+
),
177+
),
178+
),
179+
on_submit=EventActionState.on_submit, # pyright: ignore [reportCallIssue]
155180
)
156181

157182
app = rx.App(_state=rx.State)
158-
app.add_page(index)
183+
app.add_page(index) # pyright: ignore [reportArgumentType]
159184

160185

161186
@pytest.fixture(scope="module")
@@ -332,3 +357,29 @@ async def test_event_actions_throttle_debounce(
332357
await poll_for_order(
333358
["on_click_throttle"] * (exp_events - 1) + ["on_click_debounce"]
334359
)
360+
361+
362+
@pytest.mark.usefixtures("token")
363+
@pytest.mark.asyncio
364+
async def test_event_actions_dialog_form_in_form(
365+
driver: WebDriver,
366+
poll_for_order: Callable[[list[str]], Coroutine[None, None, None]],
367+
):
368+
"""Click links and buttons and assert on fired events.
369+
370+
Args:
371+
driver: WebDriver instance.
372+
poll_for_order: function that polls for the order list to match the expected order.
373+
"""
374+
open_dialog_id = "btn-dialog"
375+
submit_button_id = "btn-submit"
376+
wait = WebDriverWait(driver, 10)
377+
378+
driver.find_element(By.ID, open_dialog_id).click()
379+
el = wait.until(EC.element_to_be_clickable((By.ID, submit_button_id)))
380+
el.click() # pyright: ignore[reportAttributeAccessIssue]
381+
el.send_keys(Keys.ESCAPE) # pyright: ignore[reportAttributeAccessIssue]
382+
383+
btn_no_events = wait.until(EC.element_to_be_clickable((By.ID, "btn-no-events")))
384+
btn_no_events.click()
385+
await poll_for_order(["on_submit", "on_click:outer"])

0 commit comments

Comments
 (0)