11from __future__ import annotations
22
33from pathlib import Path
4- from pprint import pprint
54from typing import TYPE_CHECKING , Any
65from uuid import uuid4
76
87from django .forms import Form
9- from django .utils import timezone
108from reactpy import component , hooks , html , utils
119from reactpy .core .events import event
1210from reactpy .web import export , module_from_file
3028
3129
3230@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
4040 # TODO: Add auto-save option for database-backed forms
4141 uuid_ref = hooks .use_ref (uuid4 ().hex .replace ("-" , "" ))
4242 top_children_count = hooks .use_ref (len (top_children ))
4343 bottom_children_count = hooks .use_ref (len (bottom_children ))
4444 submitted_data , set_submitted_data = hooks .use_state ({} or None )
45- last_changed = hooks .use_ref (timezone .now ())
46-
4745 uuid = uuid_ref .current
4846
4947 # 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
6159 "Do NOT initialize your form by calling it (ex. `MyForm()`)."
6260 )
6361 raise TypeError (msg ) from e
64- raise
62+ raise e
6563
6664 # Run the form validation, if data was provided
6765 if submitted_data :
6866 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 ())
7468
7569 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."""
7672 convert_multiple_choice_fields (new_data , initialized_form )
7773 convert_boolean_fields (new_data , initialized_form )
7874
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.
8076 if submitted_data != new_data :
8177 set_submitted_data (new_data )
8278
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-
9679 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 ,
9881 DjangoForm ({"onSubmitCallback" : on_submit_callback , "formId" : f"reactpy-{ uuid } " }),
9982 * 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+ ),
10192 * bottom_children ,
10293 )
0 commit comments