@@ -29,22 +29,31 @@ export function Layout({ saveUpdateHook, sendEvent, loadImportSource }) {
29
29
` ;
30
30
}
31
31
32
+ const ELEMENT_WRAPPER_COMPONENTS = {
33
+ form : FormElement ,
34
+ input : UserInputElement ,
35
+ script : ScriptElement ,
36
+ select : UserInputElement ,
37
+ textarea : UserInputElement ,
38
+ } ;
39
+
32
40
export function Element ( { model } ) {
33
41
if ( model . error !== undefined ) {
34
42
if ( model . error ) {
35
43
return html `< pre > ${ model . error } </ pre > ` ;
36
44
} else {
37
45
return null ;
38
46
}
39
- } else if ( model . tagName == "script" ) {
40
- return html `< ${ ScriptElement } model =${ model } /> ` ;
41
- } else if ( [ "input" , "select" , "textarea" ] . includes ( model . tagName ) ) {
42
- return html `< ${ UserInputElement } model =${ model } /> ` ;
43
- } else if ( model . importSource ) {
44
- return html `< ${ ImportedElement } model =${ model } /> ` ;
47
+ }
48
+
49
+ let Component ;
50
+ if ( model . importSource ) {
51
+ Component = ImportedElement ;
45
52
} else {
46
- return html ` < ${ StandardElement } model = ${ model } /> ` ;
53
+ Component = ELEMENT_WRAPPER_COMPONENTS [ model . tagName ] || StandardElement ;
47
54
}
55
+
56
+ return html `< ${ Component } model =${ model } /> ` ;
48
57
}
49
58
50
59
function StandardElement ( { model } ) {
@@ -155,6 +164,41 @@ function ScriptElement({ model }) {
155
164
return html `< div ref =${ ref } / > ` ;
156
165
}
157
166
167
+ function FormElement ( { model } ) {
168
+ const layoutContext = React . useContext ( LayoutContext ) ;
169
+ const props = createElementAttributes ( model , layoutContext . sendEvent ) ;
170
+
171
+ if ( props . target && props . target !== "_self" ) {
172
+ return html `< ${ StandardElement } model =${ model } /> ` ;
173
+ }
174
+
175
+ const oldOnSubmit = props . onSubmit || ( ( ) => { } ) ;
176
+ async function onSubmit ( event ) {
177
+ event . preventDefault ( ) ;
178
+ if ( ! model ?. eventHandlers ?. onSubmit ?. preventDefault ) {
179
+ await fetch ( props . action || window . location . href , {
180
+ method : props . method || "POST" ,
181
+ body : new FormData ( event . target ) ,
182
+ } ) ;
183
+ }
184
+ if ( oldOnSubmit ) {
185
+ oldOnSubmit ( event ) ;
186
+ }
187
+ }
188
+
189
+ // Use createElement here to avoid warning about variable numbers of children not
190
+ // having keys. Warning about this must now be the responsibility of the server
191
+ // providing the models instead of the client rendering them.
192
+ return React . createElement (
193
+ model . tagName ,
194
+ { ...props , onSubmit } ,
195
+ ...createElementChildren (
196
+ model ,
197
+ ( model ) => html `< ${ Element } key =${ model . key } model=${ model } /> `
198
+ )
199
+ ) ;
200
+ }
201
+
158
202
function ImportedElement ( { model } ) {
159
203
const layoutContext = React . useContext ( LayoutContext ) ;
160
204
0 commit comments