generated from mitchell/rust_template
Various improvements #26
@ -4,11 +4,19 @@ use leptos::RwSignal;
|
||||
use std::rc::Rc;
|
||||
use web_sys::MouseEvent;
|
||||
|
||||
#[derive(Default, Clone)]
|
||||
#[derive(Clone)]
|
||||
pub struct ButtonData<FD: FormToolData> {
|
||||
pub(crate) text: String,
|
||||
pub(crate) action: Option<Rc<dyn Fn(MouseEvent, &mut FD)>>,
|
||||
}
|
||||
impl<FD: FormToolData> Default for ButtonData<FD> {
|
||||
fn default() -> Self {
|
||||
ButtonData {
|
||||
text: String::default(),
|
||||
action: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn button(
|
||||
|
||||
@ -4,9 +4,8 @@ use leptos::{CollectView, RwSignal};
|
||||
|
||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub fn group(mut self, builder: impl Fn(FormBuilder<FD, FS>) -> FormBuilder<FD, FS>) -> Self {
|
||||
let mut group_builder = FormBuilder::new_group(self.fd, self.fs);
|
||||
let mut group_builder = FormBuilder::new();
|
||||
group_builder = builder(group_builder);
|
||||
self.fs = group_builder.fs; // take the style back
|
||||
|
||||
for validation in group_builder.validations {
|
||||
self.validations.push(validation);
|
||||
|
||||
12
src/form.rs
12
src/form.rs
@ -78,7 +78,7 @@ impl<FD: FormToolData> IntoView for Form<FD> {
|
||||
///
|
||||
/// This trait defines a function that can be used to build all the data needed
|
||||
/// to physically lay out a form, and how that data should be parsed and validated.
|
||||
pub trait FormToolData: Default + Clone + 'static {
|
||||
pub trait FormToolData: Clone + 'static {
|
||||
type Style: FormStyle;
|
||||
|
||||
/// Defines how the form should be layed out and how the data should be parsed and validated.
|
||||
@ -97,9 +97,9 @@ pub trait FormToolData: Default + Clone + 'static {
|
||||
/// component. Call [`get_action_form`]\() to get the
|
||||
/// [`ActionForm`](leptos_router::ActionForm) version.
|
||||
fn get_form(self, action: impl ToString, style: Self::Style) -> Form<Self> {
|
||||
let builder = FormBuilder::new(self, style);
|
||||
let builder = FormBuilder::new();
|
||||
let builder = Self::build_form(builder);
|
||||
builder.build_plain_form(action.to_string())
|
||||
builder.build_plain_form(action.to_string(), self, style)
|
||||
}
|
||||
|
||||
/// Constructs a [`Form`] for this [`FormToolData`] type.
|
||||
@ -118,9 +118,9 @@ pub trait FormToolData: Default + Clone + 'static {
|
||||
<<ServFn::Client as Client<ServFn::Error>>::Request as ClientReq<ServFn::Error>>::FormData:
|
||||
From<FormData>,
|
||||
{
|
||||
let builder = FormBuilder::new(self, style);
|
||||
let builder = FormBuilder::new();
|
||||
let builder = Self::build_form(builder);
|
||||
builder.build_action_form(action)
|
||||
builder.build_action_form(action, self, style)
|
||||
}
|
||||
|
||||
/// Gets a [`Validator`] for this [`ToolFormData`].
|
||||
@ -132,7 +132,7 @@ pub trait FormToolData: Default + Clone + 'static {
|
||||
/// However, the code to render the views are not configured out, it
|
||||
/// simply doesn't run, so the view needs to compile even on the server.
|
||||
fn get_validator() -> FormValidator<Self> {
|
||||
let builder = FormBuilder::new(Self::default(), Self::Style::default());
|
||||
let builder = FormBuilder::new();
|
||||
let builder = Self::build_form(builder);
|
||||
builder.validator()
|
||||
}
|
||||
|
||||
@ -20,10 +20,6 @@ use web_sys::{FormData, SubmitEvent};
|
||||
///
|
||||
/// This builder allows you to specify what components should make up the form.
|
||||
pub struct FormBuilder<FD: FormToolData, FS: FormStyle> {
|
||||
/// The [`ToolFormData`] signal.
|
||||
pub(crate) fd: RwSignal<FD>,
|
||||
/// The [`FormStyle`].
|
||||
pub(crate) fs: FS,
|
||||
/// The list of [`ValidationFn`]s.
|
||||
pub(crate) validations: Vec<Rc<dyn ValidationFn<FD>>>,
|
||||
/// The list of functions that will render the form.
|
||||
@ -34,21 +30,8 @@ pub struct FormBuilder<FD: FormToolData, FS: FormStyle> {
|
||||
|
||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
/// Creates a new [`FormBuilder`]
|
||||
pub(crate) fn new(starting_data: FD, form_style: FS) -> FormBuilder<FD, FS> {
|
||||
let fd = create_rw_signal(starting_data);
|
||||
pub(crate) fn new() -> FormBuilder<FD, FS> {
|
||||
FormBuilder {
|
||||
fd,
|
||||
fs: form_style,
|
||||
validations: Vec::new(),
|
||||
render_fns: Vec::new(),
|
||||
styles: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn new_group(fd: RwSignal<FD>, fs: FS) -> FormBuilder<FD, FS> {
|
||||
FormBuilder {
|
||||
fd,
|
||||
fs,
|
||||
validations: Vec::new(),
|
||||
render_fns: Vec::new(),
|
||||
styles: Vec::new(),
|
||||
@ -232,19 +215,23 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
pub(crate) fn build_action_form<ServFn>(
|
||||
self,
|
||||
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
|
||||
fd: FD,
|
||||
fs: FS,
|
||||
) -> Form<FD>
|
||||
where
|
||||
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
|
||||
<<ServFn::Client as Client<ServFn::Error>>::Request as ClientReq<ServFn::Error>>::FormData:
|
||||
From<FormData>,
|
||||
{
|
||||
let fd = create_rw_signal(fd);
|
||||
|
||||
let (views, validation_cbs): (Vec<_>, Vec<_>) = self
|
||||
.render_fns
|
||||
.into_iter()
|
||||
.map(|r_fn| r_fn(&self.fs, self.fd))
|
||||
.map(|r_fn| r_fn(&fs, fd))
|
||||
.unzip();
|
||||
|
||||
let elements = self.fs.form_frame(views.into_view(), self.styles);
|
||||
let elements = fs.form_frame(views.into_view(), self.styles);
|
||||
|
||||
let on_submit = move |ev: SubmitEvent| {
|
||||
let mut failed = false;
|
||||
@ -265,20 +252,22 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
};
|
||||
|
||||
Form {
|
||||
fd: self.fd,
|
||||
fd,
|
||||
validations: self.validations,
|
||||
view,
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn build_plain_form(self, url: String) -> Form<FD> {
|
||||
pub(crate) fn build_plain_form(self, url: String, fd: FD, fs: FS) -> Form<FD> {
|
||||
let fd = create_rw_signal(fd);
|
||||
|
||||
let (views, validation_cbs): (Vec<_>, Vec<_>) = self
|
||||
.render_fns
|
||||
.into_iter()
|
||||
.map(|r_fn| r_fn(&self.fs, self.fd))
|
||||
.map(|r_fn| r_fn(&fs, fd))
|
||||
.unzip();
|
||||
|
||||
let elements = self.fs.form_frame(views.into_view(), self.styles);
|
||||
let elements = fs.form_frame(views.into_view(), self.styles);
|
||||
|
||||
let on_submit = move |ev: SubmitEvent| {
|
||||
let mut failed = false;
|
||||
@ -299,7 +288,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||
};
|
||||
|
||||
Form {
|
||||
fd: self.fd,
|
||||
fd,
|
||||
validations: self.validations,
|
||||
view,
|
||||
}
|
||||
|
||||
@ -13,7 +13,7 @@ use leptos::{RwSignal, Signal, View};
|
||||
|
||||
pub use grid_form::{GridFormStyle, GridFormStylingAttributes};
|
||||
|
||||
pub trait FormStyle: Default + 'static {
|
||||
pub trait FormStyle: 'static {
|
||||
type StylingAttributes;
|
||||
|
||||
/// Render any containing components for the form.
|
||||
|
||||
Reference in New Issue
Block a user