From 0564611c8e77e0f5791a3f4854bb456a8717e86a Mon Sep 17 00:00:00 2001 From: Benedikt Peetz Date: Sun, 5 Oct 2025 13:21:31 +0200 Subject: feat(form): Provide basic form framework --- src/components/form.rs | 119 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 119 insertions(+) create mode 100644 src/components/form.rs (limited to 'src/components/form.rs') diff --git a/src/components/form.rs b/src/components/form.rs new file mode 100644 index 0000000..fd55897 --- /dev/null +++ b/src/components/form.rs @@ -0,0 +1,119 @@ +macro_rules! Form { + ( + on_submit = |$bound:pat_param| $on_submit:block + $( + + )* + ) => {{ + use leptos::{ + view, + prelude::{ + Get, + NodeRef, + ElementChild, + ClassAttribute, + OnAttribute, + signal, + Set, + Show, + }, + html::Input, + web_sys::SubmitEvent + }; + + use log::info; + + + $( + let ($signal_name_get, $signal_name_set) = signal(None); + let $name: NodeRef = NodeRef::new(); + )* + + let on_submit = move |ev: SubmitEvent| { + struct Inputs { + $( + $name: $rust_type + ),* + } + + // stop the page from reloading! + ev.prevent_default(); + + $( + let value = { + let output = $name + .get() + // event handlers can only fire after the view + // is mounted to the DOM, so the `NodeRef` will be `Some` + .expect(" to exist") + .value(); + + let fin: Result<$rust_type, leptos::error::Error> = output + .parse() + .map_err(Into::::into); + fin + }; + + let $name = match value { + Ok(ok) => { + // Reset the signal + $signal_name_set.set(None); + + ok + } , + Err(err) => { + $signal_name_set.set(Some(err)); + + // Skip running the real `on_submit` + return + } + }; + )* + + let real_on_submit = |$bound| $on_submit; + real_on_submit(Inputs { + $( + $name + ),* + }) + }; + + + view! { +
+ $( + + +

{move || + format!( + "Input is invalid for type {}: {}", + stringify!($rust_type), + $signal_name_get.get().expect("Was `is_some`") + ) + }

+
+ )* + +
+ +
+ + } + }}; +} + +pub(crate) use Form; -- cgit 1.4.1