diff --git a/slhx-js/runtime/slhx.js b/slhx-js/runtime/slhx.js index b665492..8041874 100644 --- a/slhx-js/runtime/slhx.js +++ b/slhx-js/runtime/slhx.js @@ -394,6 +394,16 @@ navigate(nav); return; } + if (name === "click") { + const submitter = closestInRoot(event.target, root, "button[type=submit], input[type=submit], button:not([type])"); + const form = submitter && submitter.closest("form"); + if (form && root.contains(form) && handleId(form)) { + if (form.reportValidity && !form.reportValidity()) return; + event.preventDefault(); + schedule(form, "submit"); + return; + } + } const el = closestInRoot(event.target, root, `[${HID}], [data-slhx-boost] form`); if (!el || defaultEvent(el) !== name) return; event.preventDefault(); diff --git a/slhx-js/tests/runtime.rs b/slhx-js/tests/runtime.rs index 7877739..a9eae39 100644 --- a/slhx-js/tests/runtime.rs +++ b/slhx-js/tests/runtime.rs @@ -17,6 +17,16 @@ fn runtime_handles_get_forms_without_request_body() { assert!(source.contains("if (method === \"GET\") url.search = urlEncoded(data).toString()")); } +#[test] +fn runtime_clicking_submitter_schedules_form_submit() { + // req: convention/004 + let source = slhx_js::RUNTIME_JS; + + assert!(source.contains("button[type=submit], input[type=submit], button:not([type])")); + assert!(source.contains("form.reportValidity && !form.reportValidity()")); + assert!(source.contains("schedule(form, \"submit\")")); +} + #[test] fn runtime_supports_queued_request_policy() { let source = slhx_js::RUNTIME_JS;