add another way to build the form

This commit is contained in:
Mitchell Marino 2024-06-18 15:27:38 -05:00
parent 18a99ec181
commit e16b7fc9cb
2 changed files with 55 additions and 12 deletions

View File

@ -96,19 +96,35 @@ pub trait FormToolData: Clone + 'static {
/// Constructs a [`Form`] for this [`FormToolData`] type. /// Constructs a [`Form`] for this [`FormToolData`] type.
/// ///
/// This renders the form as a the leptos_router /// This renders the form as a enhanced
/// [`Form`](leptos_router::Form) /// [`ActionForm`](leptos_router::ActionForm) that sends the form data
/// component. Call [`get_action_form`]\() to get the /// directly by calling the server function.
/// [`ActionForm`](leptos_router::ActionForm) version. ///
fn get_form( /// By doing this, we avoid doing the [`FromFormData`](leptos_router::FromFormData)
/// conversion. However, to support
/// [Progressive Enhancement](https://book.leptos.dev/progressive_enhancement/index.html),
/// you should name the form elements to work with a plain ActionForm anyway.
/// If progresssive enhancement is not important to you, you may freely
/// use this version
///
/// For the other ways to construct a [`Form`], see:
/// - [`get_action_form`](Self::get_action_form)
/// - [`get_plain_form`](Self::get_plain_form)
fn get_form<ServFn>(
self, self,
action: impl ToString, action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
style: Self::Style, style: Self::Style,
context: Self::Context, context: Self::Context,
) -> Form<Self> { ) -> Form<Self>
where
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
<<ServFn::Client as Client<ServFn::Error>>::Request as ClientReq<ServFn::Error>>::FormData:
From<FormData>,
ServFn: From<Self>,
{
let builder = FormBuilder::new(context); let builder = FormBuilder::new(context);
let builder = Self::build_form(builder); let builder = Self::build_form(builder);
builder.build_plain_form(action.to_string(), self, style) builder.build_form(action, self, style)
} }
/// Constructs a [`Form`] for this [`FormToolData`] type. /// Constructs a [`Form`] for this [`FormToolData`] type.
@ -117,6 +133,10 @@ pub trait FormToolData: Clone + 'static {
/// [`ActionForm`](leptos_router::ActionForm) /// [`ActionForm`](leptos_router::ActionForm)
/// component. Call [`get_form`]\() to get the plain /// component. Call [`get_form`]\() to get the plain
/// [`Form`](leptos_router::Form) version. /// [`Form`](leptos_router::Form) version.
///
/// For the other ways to construct a [`Form`], see:
/// - [`get_form`](Self::get_form)
/// - [`get_action_form`](Self::get_action_form)
fn get_action_form<ServFn>( fn get_action_form<ServFn>(
self, self,
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>, action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
@ -133,6 +153,27 @@ pub trait FormToolData: Clone + 'static {
builder.build_action_form(action, self, style) builder.build_action_form(action, self, style)
} }
/// Constructs a [`Form`] for this [`FormToolData`] type.
///
/// This renders the form as a the leptos_router
/// [`Form`](leptos_router::Form)
/// component. Call [`get_action_form`]\() to get the
/// [`ActionForm`](leptos_router::ActionForm) version.
///
/// For the other ways to construct a [`Form`], see:
/// - [`get_form`](Self::get_form)
/// - [`get_action_form`](Self::get_action_form)
fn get_plain_form(
self,
action: impl ToString,
style: Self::Style,
context: Self::Context,
) -> Form<Self> {
let builder = FormBuilder::new(context);
let builder = Self::build_form(builder);
builder.build_plain_form(action.to_string(), self, style)
}
/// Gets a [`Validator`] for this [`ToolFormData`]. /// Gets a [`Validator`] for this [`ToolFormData`].
/// ///
/// This doesn't render the view, but just collects all the validation /// This doesn't render the view, but just collects all the validation

View File

@ -301,9 +301,6 @@ impl<FD: FormToolData> FormBuilder<FD> {
Rc::new(value_setter) Rc::new(value_setter)
} }
// TODO: impl build_formless function that builds the form without adding
// and form components around anything
pub(crate) fn build_form<ServFn>( pub(crate) fn build_form<ServFn>(
self, self,
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>, action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
@ -314,6 +311,7 @@ impl<FD: FormToolData> FormBuilder<FD> {
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static, ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
<<ServFn::Client as Client<ServFn::Error>>::Request as ClientReq<ServFn::Error>>::FormData: <<ServFn::Client as Client<ServFn::Error>>::Request as ClientReq<ServFn::Error>>::FormData:
From<FormData>, From<FormData>,
ServFn: From<FD>,
{ {
let fd = create_rw_signal(fd); let fd = create_rw_signal(fd);
let fs = Rc::new(fs); let fs = Rc::new(fs);
@ -338,10 +336,14 @@ impl<FD: FormToolData> FormBuilder<FD> {
} }
if failed { if failed {
ev.prevent_default(); ev.prevent_default();
return;
} }
ev.prevent_default();
let server_fn = ServFn::from(fd.get_untracked());
action.dispatch(server_fn);
}; };
// TODO: do enhanced form with direct calling of the server_fn
let view = view! { let view = view! {
<ActionForm action=action on:submit=on_submit> <ActionForm action=action on:submit=on_submit>
{elements} {elements}