1
1
from __future__ import annotations
2
2
3
3
from pathlib import Path
4
- from pprint import pprint
5
4
from typing import TYPE_CHECKING , Any
6
5
from uuid import uuid4
7
6
8
7
from django .forms import Form
9
- from django .utils import timezone
10
8
from reactpy import component , hooks , html , utils
11
9
from reactpy .core .events import event
12
10
from reactpy .web import export , module_from_file
30
28
31
29
32
30
@component
33
- def _django_form (form : type [Form ], top_children : Sequence , bottom_children : Sequence ):
34
- # TODO: Implement form restoration on page reload. Probably want to create a new setting called
35
- # form_restoration_method that can be set to "URL", "CLIENT_STORAGE", "SERVER_SESSION", or None.
36
- # Or maybe just recommend pre-rendering to have the browser handle it.
37
- # Be clear that URL mode will limit you to one form per page.
38
- # TODO: Test this with django-bootstrap, django-colorfield, django-ace, django-crispy-forms
39
- # TODO: Add pre-submit and post-submit hooks
31
+ def _django_form (
32
+ form : type [Form ], extra_props : dict , form_template : str | None , top_children : Sequence , bottom_children : Sequence
33
+ ):
34
+ # TODO: Implement form restoration on page reload. Maybe this involves creating a new setting called
35
+ # `form_restoration_method` that can be set to "URL", "CLIENT_STORAGE", "SERVER_SESSION", or None.
36
+ # Perhaps pre-rendering is robust enough already handle this scenario?
37
+ # Additionaly, "URL" mode would limit the user to one form per page.
38
+ # TODO: Test this with django-colorfield, django-ace, django-crispy-forms
39
+ # TODO: Add pre-submit, post-submit, error, and success hooks
40
40
# TODO: Add auto-save option for database-backed forms
41
41
uuid_ref = hooks .use_ref (uuid4 ().hex .replace ("-" , "" ))
42
42
top_children_count = hooks .use_ref (len (top_children ))
43
43
bottom_children_count = hooks .use_ref (len (bottom_children ))
44
44
submitted_data , set_submitted_data = hooks .use_state ({} or None )
45
- last_changed = hooks .use_ref (timezone .now ())
46
-
47
45
uuid = uuid_ref .current
48
46
49
47
# Don't allow the count of top and bottom children to change
@@ -61,42 +59,35 @@ def _django_form(form: type[Form], top_children: Sequence, bottom_children: Sequ
61
59
"Do NOT initialize your form by calling it (ex. `MyForm()`)."
62
60
)
63
61
raise TypeError (msg ) from e
64
- raise
62
+ raise e
65
63
66
64
# Run the form validation, if data was provided
67
65
if submitted_data :
68
66
initialized_form .full_clean ()
69
-
70
- @event (prevent_default = True )
71
- def on_submit (_event ):
72
- """The server was notified that a form was submitted. Note that actual submission behavior is handled by `on_submit_callback`."""
73
- last_changed .set_current (timezone .now ())
67
+ print ("Form errors:" , initialized_form .errors .as_data ())
74
68
75
69
def on_submit_callback (new_data : dict [str , Any ]):
70
+ """Callback function provided directly to the client side listener. This is responsible for transmitting
71
+ the submitted form data to the server for processing."""
76
72
convert_multiple_choice_fields (new_data , initialized_form )
77
73
convert_boolean_fields (new_data , initialized_form )
78
74
79
- # TODO: ReactPy's use_state hook really should be de-duplicating this by itself. Needs upstream fix.
75
+ # TODO: The ` use_state`` hook really should be de-duplicating this by itself. Needs upstream fix.
80
76
if submitted_data != new_data :
81
77
set_submitted_data (new_data )
82
78
83
- def on_change (_event ):
84
- last_changed .set_current (timezone .now ())
85
-
86
- rendered_form = utils .html_to_vdom (
87
- initialized_form .render (),
88
- convert_html_props_to_reactjs ,
89
- convert_textarea_children_to_prop ,
90
- set_value_prop_on_select_element ,
91
- ensure_input_elements_are_controlled (on_change ),
92
- intercept_anchor_links ,
93
- strict = False ,
94
- )
95
-
96
79
return html .form (
97
- {"id" : f"reactpy-{ uuid } " , "onSubmit" : on_submit } ,
80
+ {"id" : f"reactpy-{ uuid } " , "onSubmit" : event ( lambda _ : None , prevent_default = True )} | extra_props ,
98
81
DjangoForm ({"onSubmitCallback" : on_submit_callback , "formId" : f"reactpy-{ uuid } " }),
99
82
* top_children ,
100
- rendered_form ,
83
+ utils .html_to_vdom (
84
+ initialized_form .render (form_template ),
85
+ convert_html_props_to_reactjs ,
86
+ convert_textarea_children_to_prop ,
87
+ set_value_prop_on_select_element ,
88
+ ensure_input_elements_are_controlled (),
89
+ intercept_anchor_links ,
90
+ strict = False ,
91
+ ),
101
92
* bottom_children ,
102
93
)
0 commit comments