11from __future__ import annotations
22
33from pathlib import Path
4- from typing import TYPE_CHECKING , Any
4+ from typing import TYPE_CHECKING , Any , Callable
55from uuid import uuid4
66
77from django .forms import Form
1717 set_value_prop_on_select_element ,
1818)
1919from reactpy_django .forms .utils import convert_boolean_fields , convert_multiple_choice_fields
20+ from reactpy_django .types import FormEvent
2021
2122if TYPE_CHECKING :
2223 from collections .abc import Sequence
2930
3031@component
3132def _django_form (
32- form : type [Form ], extra_props : dict , form_template : str | None , top_children : Sequence , bottom_children : Sequence
33+ form : type [Form ],
34+ extra_props : dict ,
35+ on_success : Callable [[FormEvent ], None ] | None ,
36+ on_error : Callable [[FormEvent ], None ] | None ,
37+ on_submit : Callable [[FormEvent ], None ] | None ,
38+ form_template : str | None ,
39+ top_children : Sequence ,
40+ bottom_children : Sequence ,
3341):
3442 # TODO: Implement form restoration on page reload. Maybe this involves creating a new setting called
3543 # `form_restoration_method` that can be set to "URL", "CLIENT_STORAGE", "SERVER_SESSION", or None.
3644 # Perhaps pre-rendering is robust enough already handle this scenario?
37- # Additionaly , "URL" mode would limit the user to one form per page.
45+ # Additionally , "URL" mode would limit the user to one form per page.
3846 # TODO: Test this with django-colorfield, django-ace, django-crispy-forms
39- # TODO: Add pre-submit, post-submit, error, and success hooks
4047 # TODO: Add auto-save option for database-backed forms
4148 uuid_ref = hooks .use_ref (uuid4 ().hex .replace ("-" , "" ))
4249 top_children_count = hooks .use_ref (len (top_children ))
@@ -59,12 +66,17 @@ def _django_form(
5966 "Do NOT initialize your form by calling it (ex. `MyForm()`)."
6067 )
6168 raise TypeError (msg ) from e
62- raise e
69+ raise
6370
6471 # Run the form validation, if data was provided
6572 if submitted_data :
6673 initialized_form .full_clean ()
67- print ("Form errors:" , initialized_form .errors .as_data ())
74+ success = not initialized_form .errors .as_data ()
75+ form_event = FormEvent (form = initialized_form , data = submitted_data or {})
76+ if success and on_success :
77+ on_success (form_event )
78+ if not success and on_error :
79+ on_error (form_event )
6880
6981 def on_submit_callback (new_data : dict [str , Any ]):
7082 """Callback function provided directly to the client side listener. This is responsible for transmitting
@@ -74,6 +86,8 @@ def on_submit_callback(new_data: dict[str, Any]):
7486
7587 # TODO: The `use_state`` hook really should be de-duplicating this by itself. Needs upstream fix.
7688 if submitted_data != new_data :
89+ if on_submit :
90+ on_submit (FormEvent (form = initialized_form , data = new_data ))
7791 set_submitted_data (new_data )
7892
7993 return html .form (
0 commit comments