1
1
from __future__ import annotations
2
2
3
3
from pathlib import Path
4
- from typing import TYPE_CHECKING , Any
4
+ from typing import TYPE_CHECKING , Any , Callable
5
5
from uuid import uuid4
6
6
7
7
from django .forms import Form
17
17
set_value_prop_on_select_element ,
18
18
)
19
19
from reactpy_django .forms .utils import convert_boolean_fields , convert_multiple_choice_fields
20
+ from reactpy_django .types import FormEvent
20
21
21
22
if TYPE_CHECKING :
22
23
from collections .abc import Sequence
29
30
30
31
@component
31
32
def _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 ,
33
41
):
34
42
# TODO: Implement form restoration on page reload. Maybe this involves creating a new setting called
35
43
# `form_restoration_method` that can be set to "URL", "CLIENT_STORAGE", "SERVER_SESSION", or None.
36
44
# 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.
38
46
# TODO: Test this with django-colorfield, django-ace, django-crispy-forms
39
- # TODO: Add pre-submit, post-submit, error, and success hooks
40
47
# TODO: Add auto-save option for database-backed forms
41
48
uuid_ref = hooks .use_ref (uuid4 ().hex .replace ("-" , "" ))
42
49
top_children_count = hooks .use_ref (len (top_children ))
@@ -59,12 +66,17 @@ def _django_form(
59
66
"Do NOT initialize your form by calling it (ex. `MyForm()`)."
60
67
)
61
68
raise TypeError (msg ) from e
62
- raise e
69
+ raise
63
70
64
71
# Run the form validation, if data was provided
65
72
if submitted_data :
66
73
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 )
68
80
69
81
def on_submit_callback (new_data : dict [str , Any ]):
70
82
"""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]):
74
86
75
87
# TODO: The `use_state`` hook really should be de-duplicating this by itself. Needs upstream fix.
76
88
if submitted_data != new_data :
89
+ if on_submit :
90
+ on_submit (FormEvent (form = initialized_form , data = new_data ))
77
91
set_submitted_data (new_data )
78
92
79
93
return html .form (
0 commit comments