generated from mitchell/rust_template
cleanup
This commit is contained in:
parent
68d6b857ed
commit
74407d6c0a
@ -90,24 +90,24 @@
|
|||||||
|
|
||||||
|
|
||||||
// column widths
|
// column widths
|
||||||
.w-full {
|
.col-span-full {
|
||||||
grid-column: 1 / -1;
|
grid-column: 1 / -1;
|
||||||
}
|
}
|
||||||
.w-12 {
|
.col-span-12 {
|
||||||
grid-column: span 12 / span 12;
|
grid-column: span 12 / span 12;
|
||||||
}
|
}
|
||||||
.w-6 {
|
.col-span-6 {
|
||||||
grid-column: span 6 / span 6;
|
grid-column: span 6 / span 6;
|
||||||
}
|
}
|
||||||
.w-4 {
|
.col-span-4 {
|
||||||
grid-column: span 4 / span 4;
|
grid-column: span 4 / span 4;
|
||||||
}
|
}
|
||||||
.w-3 {
|
.col-span-3 {
|
||||||
grid-column: span 3 / span 3;
|
grid-column: span 3 / span 3;
|
||||||
}
|
}
|
||||||
.w-2 {
|
.col-span-2 {
|
||||||
grid-column: span 2 / span 2;
|
grid-column: span 2 / span 2;
|
||||||
}
|
}
|
||||||
.w-1 {
|
.col-span-1 {
|
||||||
grid-column: span 1 / span 1;
|
grid-column: span 1 / span 1;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -53,6 +53,11 @@ impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormData, FS: FormStyle, FDT> ControlBuilder<FD, FS, TextInputData, FDT> {
|
impl<FD: FormData, FS: FormStyle, FDT> ControlBuilder<FD, FS, TextInputData, FDT> {
|
||||||
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
|
self.data.name = control_name.to_string();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
pub fn placeholder(mut self, placeholder: impl ToString) -> Self {
|
pub fn placeholder(mut self, placeholder: impl ToString) -> Self {
|
||||||
self.data.placeholder = Some(placeholder.to_string());
|
self.data.placeholder = Some(placeholder.to_string());
|
||||||
self
|
self
|
||||||
|
|||||||
80
src/form.rs
80
src/form.rs
@ -7,10 +7,8 @@ use crate::{
|
|||||||
},
|
},
|
||||||
styles::FormStyle,
|
styles::FormStyle,
|
||||||
};
|
};
|
||||||
use leptos::{
|
use leptos::*;
|
||||||
create_rw_signal, create_signal, IntoSignal, IntoView, RwSignal, SignalGet, SignalSet,
|
use leptos_router::Form;
|
||||||
SignalUpdate, View,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub struct Validator<FD: FormData> {
|
pub struct Validator<FD: FormData> {
|
||||||
validations: Vec<Rc<dyn ValidationFn<FD>>>,
|
validations: Vec<Rc<dyn ValidationFn<FD>>>,
|
||||||
@ -102,20 +100,8 @@ pub struct FormBuilder<FD: FormData, FS: FormStyle> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
||||||
// TODO: remove the Default trait bound and bind it to this function only
|
// TODO: remove the Default trait bound
|
||||||
fn new_full_builder(form_style: FS) -> FormBuilder<FD, FS> {
|
fn new_full_builder(starting_data: FD, form_style: FS) -> FormBuilder<FD, FS> {
|
||||||
let fd = create_rw_signal(FD::default());
|
|
||||||
FormBuilder {
|
|
||||||
inner: FormBuilderInner::FullBuilder(FullFormBuilder {
|
|
||||||
fd,
|
|
||||||
fs: form_style,
|
|
||||||
validations: Vec::new(),
|
|
||||||
views: Vec::new(),
|
|
||||||
}),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn new_full_builder_with(starting_data: FD, form_style: FS) -> FormBuilder<FD, FS> {
|
|
||||||
let fd = create_rw_signal(starting_data);
|
let fd = create_rw_signal(starting_data);
|
||||||
FormBuilder {
|
FormBuilder {
|
||||||
inner: FormBuilderInner::FullBuilder(FullFormBuilder {
|
inner: FormBuilderInner::FullBuilder(FullFormBuilder {
|
||||||
@ -267,12 +253,38 @@ impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build(self) -> Option<Form<FD>> {
|
fn build(
|
||||||
|
self,
|
||||||
|
action_location: String,
|
||||||
|
action: Option<Action<FD, Result<(), ServerFnError>>>,
|
||||||
|
) -> Option<Form<FD>> {
|
||||||
let builder = match self.inner {
|
let builder = match self.inner {
|
||||||
FormBuilderInner::FullBuilder(fb) => fb,
|
FormBuilderInner::FullBuilder(fb) => fb,
|
||||||
FormBuilderInner::ValidationBuilder { validations: _ } => return None,
|
FormBuilderInner::ValidationBuilder { validations: _ } => return None,
|
||||||
};
|
};
|
||||||
let view = builder.fs.form_frame(builder.views.into_view());
|
let validations = builder.validations.clone();
|
||||||
|
let validate_form = move || {
|
||||||
|
let fd = builder.fd.get();
|
||||||
|
validations.iter().all(|v| v(&fd).is_ok())
|
||||||
|
};
|
||||||
|
|
||||||
|
let elements = builder.fs.form_frame(builder.views.into_view());
|
||||||
|
|
||||||
|
let view = view! {
|
||||||
|
<Form action=action_location
|
||||||
|
on:submit=move |ev| {
|
||||||
|
if !validate_form() {
|
||||||
|
ev.prevent_default();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if let Some(action) = action {
|
||||||
|
action.dispatch(builder.fd.get());
|
||||||
|
}
|
||||||
|
}>
|
||||||
|
{elements}
|
||||||
|
</Form>
|
||||||
|
}
|
||||||
|
.into_view();
|
||||||
|
|
||||||
Some(Form {
|
Some(Form {
|
||||||
fd: builder.fd,
|
fd: builder.fd,
|
||||||
@ -281,10 +293,10 @@ impl<FD: FormData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn validator(self) -> Validator<FD> {
|
fn validator(&self) -> Validator<FD> {
|
||||||
let validations = match self.inner {
|
let validations = match &self.inner {
|
||||||
FormBuilderInner::FullBuilder(fb) => fb.validations,
|
FormBuilderInner::FullBuilder(fb) => fb.validations.clone(),
|
||||||
FormBuilderInner::ValidationBuilder { validations } => validations,
|
FormBuilderInner::ValidationBuilder { validations } => validations.clone(),
|
||||||
};
|
};
|
||||||
Validator { validations }
|
Validator { validations }
|
||||||
}
|
}
|
||||||
@ -309,16 +321,24 @@ pub trait FormData: Default + Clone + 'static {
|
|||||||
/// Constructs a [`Form`] for this FormData type.
|
/// Constructs a [`Form`] for this FormData type.
|
||||||
///
|
///
|
||||||
/// The [`Form`] provides the way to render the form.
|
/// The [`Form`] provides the way to render the form.
|
||||||
fn get_form(style: Self::Style) -> Form<Self> {
|
fn get_form(self, action: impl ToString, style: Self::Style) -> Form<Self> {
|
||||||
let builder = FormBuilder::new_full_builder(style);
|
let builder = FormBuilder::new_full_builder(self, style);
|
||||||
let builder = Self::build_form(builder);
|
let builder = Self::build_form(builder);
|
||||||
builder.build().expect("builder should be full builder")
|
builder
|
||||||
|
.build(action.to_string(), None)
|
||||||
|
.expect("builder should be full builder")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_form_with_starting_data(self, style: Self::Style) -> Form<Self> {
|
fn get_action_form(
|
||||||
let builder = FormBuilder::new_full_builder_with(self, style);
|
self,
|
||||||
|
action: Action<Self, Result<(), ServerFnError>>,
|
||||||
|
style: Self::Style,
|
||||||
|
) -> Form<Self> {
|
||||||
|
let builder = FormBuilder::new_full_builder(self, style);
|
||||||
let builder = Self::build_form(builder);
|
let builder = Self::build_form(builder);
|
||||||
builder.build().expect("builder should be full builder")
|
builder
|
||||||
|
.build(action.url().unwrap_or(String::new()), Some(action))
|
||||||
|
.expect("builder should be full builder")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_validator() -> Validator<Self> {
|
fn get_validator() -> Validator<Self> {
|
||||||
|
|||||||
@ -4,7 +4,6 @@ use crate::controls::{
|
|||||||
text_input::TextInputData, ControlData, ControlRenderData,
|
text_input::TextInputData, ControlData, ControlRenderData,
|
||||||
};
|
};
|
||||||
use leptos::*;
|
use leptos::*;
|
||||||
use leptos_router::Form;
|
|
||||||
|
|
||||||
pub enum GridFormStylingAttributes {
|
pub enum GridFormStylingAttributes {
|
||||||
Width(u32),
|
Width(u32),
|
||||||
@ -16,12 +15,11 @@ pub struct GridFormStyle;
|
|||||||
impl FormStyle for GridFormStyle {
|
impl FormStyle for GridFormStyle {
|
||||||
type StylingAttributes = GridFormStylingAttributes;
|
type StylingAttributes = GridFormStylingAttributes;
|
||||||
|
|
||||||
// TODO: something about an on-submit thing
|
|
||||||
fn form_frame(&self, children: View) -> View {
|
fn form_frame(&self, children: View) -> View {
|
||||||
view! {
|
view! {
|
||||||
<Form action="" class="form_grid">
|
<div class="form_grid">
|
||||||
{children}
|
{children}
|
||||||
</Form>
|
</div>
|
||||||
}
|
}
|
||||||
.into_view()
|
.into_view()
|
||||||
}
|
}
|
||||||
@ -118,7 +116,7 @@ impl FormStyle for GridFormStyle {
|
|||||||
<input
|
<input
|
||||||
type="submit"
|
type="submit"
|
||||||
value=control.data.text
|
value=control.data.text
|
||||||
class="w-full form_submit"
|
class="col-span-full form_submit"
|
||||||
/>
|
/>
|
||||||
}
|
}
|
||||||
.into_view()
|
.into_view()
|
||||||
|
|||||||
@ -10,6 +10,13 @@ use leptos::{Signal, View};
|
|||||||
pub trait FormStyle: Default + 'static {
|
pub trait FormStyle: Default + 'static {
|
||||||
type StylingAttributes;
|
type StylingAttributes;
|
||||||
|
|
||||||
|
/// Render any containing components for the form.
|
||||||
|
///
|
||||||
|
/// This allows you to wrap all the form components
|
||||||
|
/// in another component if neccisary.
|
||||||
|
///
|
||||||
|
/// Do NOT wrap it in an actual `form` element; any
|
||||||
|
/// wrapping should be done with `div` or similar elements.
|
||||||
fn form_frame(&self, children: View) -> View;
|
fn form_frame(&self, children: View) -> View;
|
||||||
fn heading(&self, control: ControlRenderData<Self, HeadingData>) -> View;
|
fn heading(&self, control: ControlRenderData<Self, HeadingData>) -> View;
|
||||||
fn text_input(
|
fn text_input(
|
||||||
|
|||||||
Reference in New Issue
Block a user