generated from mitchell/rust_template
Merge pull request 'Add context' (#27) from feature/context into main
Reviewed-on: #27
This commit is contained in:
commit
7d855e764f
@ -1,12 +1,11 @@
|
|||||||
use super::ControlRenderData;
|
use super::{BuilderFn, ControlRenderData};
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
use leptos::RwSignal;
|
use leptos::RwSignal;
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use web_sys::MouseEvent;
|
use web_sys::MouseEvent;
|
||||||
|
|
||||||
type ButtonAction<FD> = dyn Fn(MouseEvent, &mut FD);
|
type ButtonAction<FD> = dyn Fn(MouseEvent, RwSignal<FD>) + 'static;
|
||||||
|
|
||||||
#[derive(Clone)]
|
|
||||||
pub struct ButtonData<FD: FormToolData> {
|
pub struct ButtonData<FD: FormToolData> {
|
||||||
pub(crate) text: String,
|
pub(crate) text: String,
|
||||||
pub(crate) action: Option<Rc<ButtonAction<FD>>>,
|
pub(crate) action: Option<Rc<ButtonAction<FD>>>,
|
||||||
@ -19,21 +18,26 @@ impl<FD: FormToolData> Default for ButtonData<FD> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<FD: FormToolData> Clone for ButtonData<FD> {
|
||||||
|
fn clone(&self) -> Self {
|
||||||
|
ButtonData {
|
||||||
|
text: self.text.clone(),
|
||||||
|
action: self.action.clone(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn button(
|
pub fn button(mut self, builder: impl BuilderFn<ButtonBuilder<FD>, FD::Context>) -> Self {
|
||||||
mut self,
|
|
||||||
builder: impl Fn(ButtonBuilder<FD, FS>) -> ButtonBuilder<FD, FS>,
|
|
||||||
) -> Self {
|
|
||||||
let button_builder = ButtonBuilder::new();
|
let button_builder = ButtonBuilder::new();
|
||||||
let control = builder(button_builder);
|
let control = builder(button_builder, &self.cx);
|
||||||
|
|
||||||
let render_data = ControlRenderData {
|
let render_data = ControlRenderData {
|
||||||
data: control.data,
|
data: control.data,
|
||||||
styles: control.styles,
|
styles: control.styles,
|
||||||
};
|
};
|
||||||
|
|
||||||
let render_fn = move |fs: &FS, fd: RwSignal<FD>| {
|
let render_fn = move |fs: &FD::Style, fd: RwSignal<FD>| {
|
||||||
let view = fs.button(render_data, fd);
|
let view = fs.button(render_data, fd);
|
||||||
(view, None)
|
(view, None)
|
||||||
};
|
};
|
||||||
@ -43,13 +47,12 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
pub struct ButtonBuilder<FD: FormToolData> {
|
||||||
pub struct ButtonBuilder<FD: FormToolData, FS: FormStyle> {
|
pub(crate) styles: Vec<<FD::Style as FormStyle>::StylingAttributes>,
|
||||||
pub(crate) styles: Vec<FS::StylingAttributes>,
|
|
||||||
pub(crate) data: ButtonData<FD>,
|
pub(crate) data: ButtonData<FD>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> ButtonBuilder<FD, FS> {
|
impl<FD: FormToolData> ButtonBuilder<FD> {
|
||||||
fn new() -> Self {
|
fn new() -> Self {
|
||||||
ButtonBuilder {
|
ButtonBuilder {
|
||||||
styles: Vec::default(),
|
styles: Vec::default(),
|
||||||
@ -57,7 +60,7 @@ impl<FD: FormToolData, FS: FormStyle> ButtonBuilder<FD, FS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style(mut self, style: FS::StylingAttributes) -> Self {
|
pub fn style(mut self, style: <FD::Style as FormStyle>::StylingAttributes) -> Self {
|
||||||
self.styles.push(style);
|
self.styles.push(style);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -67,7 +70,7 @@ impl<FD: FormToolData, FS: FormStyle> ButtonBuilder<FD, FS> {
|
|||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn action(mut self, action: impl Fn(MouseEvent, &mut FD) + 'static) -> Self {
|
pub fn action(mut self, action: impl Fn(MouseEvent, RwSignal<FD>) + 'static) -> Self {
|
||||||
self.data.action = Some(Rc::new(action));
|
self.data.action = Some(Rc::new(action));
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{Signal, View};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData};
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct CheckboxData {
|
pub struct CheckboxData {
|
||||||
@ -23,18 +22,16 @@ impl ControlData for CheckboxData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn checkbox<FDT: Clone + PartialEq + 'static>(
|
pub fn checkbox<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, CheckboxData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, CheckboxData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, CheckboxData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, CheckboxData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, CheckboxData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
use super::{ControlBuilder, ControlData};
|
use super::{BuilderFn, ControlBuilder, ControlData};
|
||||||
use crate::{styles::FormStyle, FormBuilder, FormToolData};
|
use crate::{FormBuilder, FormToolData};
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn custom<CC: ControlData, FDT: Clone + PartialEq + 'static>(
|
pub fn custom<CC: ControlData, FDT: Clone + PartialEq + 'static>(
|
||||||
mut self,
|
mut self,
|
||||||
control_data: CC,
|
control_data: CC,
|
||||||
builder: impl Fn(ControlBuilder<FD, FS, CC, FDT>) -> ControlBuilder<FD, FS, CC, FDT>,
|
builder: impl Fn(ControlBuilder<FD, CC, FDT>) -> ControlBuilder<FD, CC, FDT>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let control_builder = ControlBuilder::new(control_data);
|
let control_builder = ControlBuilder::new(control_data);
|
||||||
let control = builder(control_builder);
|
let control = builder(control_builder);
|
||||||
@ -15,7 +15,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
|
|
||||||
pub fn custom_default<CC: Default + ControlData, FDT: Clone + PartialEq + 'static>(
|
pub fn custom_default<CC: Default + ControlData, FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(ControlBuilder<FD, FS, CC, FDT>) -> ControlBuilder<FD, FS, CC, FDT>,
|
builder: impl BuilderFn<ControlBuilder<FD, CC, FDT>, FD::Context>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,17 +1,21 @@
|
|||||||
use super::ValidationCb;
|
use super::ValidationCb;
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::styles::FormStyle;
|
||||||
|
use crate::{form::FormToolData, form_builder::FormBuilder};
|
||||||
use leptos::{CollectView, RwSignal};
|
use leptos::{CollectView, RwSignal};
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn group(mut self, builder: impl Fn(FormBuilder<FD, FS>) -> FormBuilder<FD, FS>) -> Self {
|
pub fn group(mut self, builder: impl Fn(FormBuilder<FD>) -> FormBuilder<FD>) -> Self {
|
||||||
let mut group_builder = FormBuilder::new();
|
let mut group_builder = FormBuilder::new_group(self.cx);
|
||||||
group_builder = builder(group_builder);
|
group_builder = builder(group_builder);
|
||||||
|
|
||||||
|
// Take context back
|
||||||
|
self.cx = group_builder.cx;
|
||||||
|
|
||||||
for validation in group_builder.validations {
|
for validation in group_builder.validations {
|
||||||
self.validations.push(validation);
|
self.validations.push(validation);
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_fn = move |fs: &FS, fd: RwSignal<FD>| {
|
let render_fn = move |fs: &FD::Style, fd: RwSignal<FD>| {
|
||||||
let (views, validation_cbs): (Vec<_>, Vec<_>) = group_builder
|
let (views, validation_cbs): (Vec<_>, Vec<_>) = group_builder
|
||||||
.render_fns
|
.render_fns
|
||||||
.into_iter()
|
.into_iter()
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{ControlRenderData, VanityControlBuilder, VanityControlData};
|
use super::{BuilderFn, ControlRenderData, VanityControlBuilder, VanityControlData};
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
use leptos::View;
|
use leptos::View;
|
||||||
|
|
||||||
@ -17,18 +17,16 @@ impl VanityControlData for HeadingData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn heading(
|
pub fn heading(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<VanityControlBuilder<FD, HeadingData>, FD::Context>,
|
||||||
VanityControlBuilder<FD, FS, HeadingData>,
|
|
||||||
) -> VanityControlBuilder<FD, FS, HeadingData>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_vanity(builder)
|
self.new_vanity(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> VanityControlBuilder<FD, FS, HeadingData> {
|
impl<FD: FormToolData> VanityControlBuilder<FD, HeadingData> {
|
||||||
pub fn title(mut self, title: impl ToString) -> Self {
|
pub fn title(mut self, title: impl ToString) -> Self {
|
||||||
self.data.title = title.to_string();
|
self.data.title = title.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{Signal, View};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData};
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct HiddenData;
|
pub struct HiddenData;
|
||||||
@ -20,12 +19,10 @@ impl ControlData for HiddenData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn hidden<FDT: Clone + PartialEq + 'static>(
|
pub fn hidden<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, HiddenData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, HiddenData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, HiddenData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -18,6 +18,7 @@ pub mod submit;
|
|||||||
pub mod text_area;
|
pub mod text_area;
|
||||||
pub mod text_input;
|
pub mod text_input;
|
||||||
|
|
||||||
|
pub trait BuilderFn<B, CX>: Fn(B, &CX) -> B {}
|
||||||
pub trait ValidationFn<FDT>: Fn(&FDT) -> Result<(), String> + 'static {}
|
pub trait ValidationFn<FDT>: Fn(&FDT) -> Result<(), String> + 'static {}
|
||||||
pub trait ValidationCb: Fn() -> bool + 'static {}
|
pub trait ValidationCb: Fn() -> bool + 'static {}
|
||||||
pub trait ParseFn<CR, FDT>: Fn(CR) -> Result<FDT, String> + 'static {}
|
pub trait ParseFn<CR, FDT>: Fn(CR) -> Result<FDT, String> + 'static {}
|
||||||
@ -30,6 +31,7 @@ pub trait RenderFn<FS, FD>:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// implement the traits for all valid types
|
// implement the traits for all valid types
|
||||||
|
impl<B, CX, T> BuilderFn<B, CX> for T where T: Fn(B, &CX) -> B {}
|
||||||
impl<FDT, T> ValidationFn<FDT> for T where T: Fn(&FDT) -> Result<(), String> + 'static {}
|
impl<FDT, T> ValidationFn<FDT> for T where T: Fn(&FDT) -> Result<(), String> + 'static {}
|
||||||
impl<T> ValidationCb for T where T: Fn() -> bool + 'static {}
|
impl<T> ValidationCb for T where T: Fn() -> bool + 'static {}
|
||||||
impl<CR, FDT, F> ParseFn<CR, FDT> for F where F: Fn(CR) -> Result<FDT, String> + 'static {}
|
impl<CR, FDT, F> ParseFn<CR, FDT> for F where F: Fn(CR) -> Result<FDT, String> + 'static {}
|
||||||
@ -75,18 +77,18 @@ pub struct ControlRenderData<FS: FormStyle + ?Sized, C: ?Sized> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The data needed to render a read-only control of type `C`.
|
/// The data needed to render a read-only control of type `C`.
|
||||||
pub struct VanityControlBuilder<FD: FormToolData, FS: FormStyle, C: VanityControlData> {
|
pub struct VanityControlBuilder<FD: FormToolData, C: VanityControlData> {
|
||||||
pub(crate) style_attributes: Vec<FS::StylingAttributes>,
|
pub(crate) style_attributes: Vec<<FD::Style as FormStyle>::StylingAttributes>,
|
||||||
pub(crate) data: C,
|
pub(crate) data: C,
|
||||||
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, String>>>,
|
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) struct BuiltVanityControlData<FD: FormToolData, FS: FormStyle, C: VanityControlData> {
|
pub(crate) struct BuiltVanityControlData<FD: FormToolData, C: VanityControlData> {
|
||||||
pub(crate) render_data: ControlRenderData<FS, C>,
|
pub(crate) render_data: ControlRenderData<FD::Style, C>,
|
||||||
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, String>>>,
|
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, String>>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, C: VanityControlData> VanityControlBuilder<FD, FS, C> {
|
impl<FD: FormToolData, C: VanityControlData> VanityControlBuilder<FD, C> {
|
||||||
/// Creates a new [`VanityControlBuilder`] with the given [`VanityControlData`].
|
/// Creates a new [`VanityControlBuilder`] with the given [`VanityControlData`].
|
||||||
pub(crate) fn new(data: C) -> Self {
|
pub(crate) fn new(data: C) -> Self {
|
||||||
VanityControlBuilder {
|
VanityControlBuilder {
|
||||||
@ -97,7 +99,7 @@ impl<FD: FormToolData, FS: FormStyle, C: VanityControlData> VanityControlBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the builder into the data needed to render the control.
|
/// Builds the builder into the data needed to render the control.
|
||||||
pub(crate) fn build(self) -> BuiltVanityControlData<FD, FS, C> {
|
pub(crate) fn build(self) -> BuiltVanityControlData<FD, C> {
|
||||||
BuiltVanityControlData {
|
BuiltVanityControlData {
|
||||||
render_data: ControlRenderData {
|
render_data: ControlRenderData {
|
||||||
data: self.data,
|
data: self.data,
|
||||||
@ -108,13 +110,13 @@ impl<FD: FormToolData, FS: FormStyle, C: VanityControlData> VanityControlBuilder
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a styling attribute to this control.
|
/// Adds a styling attribute to this control.
|
||||||
pub fn style(mut self, attribute: FS::StylingAttributes) -> Self {
|
pub fn style(mut self, attribute: <FD::Style as FormStyle>::StylingAttributes) -> Self {
|
||||||
self.style_attributes.push(attribute);
|
self.style_attributes.push(attribute);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, C: GetterVanityControlData> VanityControlBuilder<FD, FS, C> {
|
impl<FD: FormToolData, C: GetterVanityControlData> VanityControlBuilder<FD, C> {
|
||||||
/// Sets the getter function.
|
/// Sets the getter function.
|
||||||
///
|
///
|
||||||
/// This function can get a string from the form data to be displayed
|
/// This function can get a string from the form data to be displayed
|
||||||
@ -151,8 +153,8 @@ impl Display for ControlBuildError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// The data returned fomr a control's build function.
|
/// The data returned fomr a control's build function.
|
||||||
pub(crate) struct BuiltControlData<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> {
|
pub(crate) struct BuiltControlData<FD: FormToolData, C: ControlData, FDT> {
|
||||||
pub(crate) render_data: ControlRenderData<FS, C>,
|
pub(crate) render_data: ControlRenderData<FD::Style, C>,
|
||||||
pub(crate) getter: Rc<dyn FieldGetter<FD, FDT>>,
|
pub(crate) getter: Rc<dyn FieldGetter<FD, FDT>>,
|
||||||
pub(crate) setter: Rc<dyn FieldSetter<FD, FDT>>,
|
pub(crate) setter: Rc<dyn FieldSetter<FD, FDT>>,
|
||||||
pub(crate) parse_fn: Box<dyn ParseFn<C::ReturnType, FDT>>,
|
pub(crate) parse_fn: Box<dyn ParseFn<C::ReturnType, FDT>>,
|
||||||
@ -161,17 +163,17 @@ pub(crate) struct BuiltControlData<FD: FormToolData, FS: FormStyle, C: ControlDa
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A builder for a interactive control.
|
/// A builder for a interactive control.
|
||||||
pub struct ControlBuilder<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> {
|
pub struct ControlBuilder<FD: FormToolData, C: ControlData, FDT> {
|
||||||
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, FDT>>>,
|
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, FDT>>>,
|
||||||
pub(crate) setter: Option<Rc<dyn FieldSetter<FD, FDT>>>,
|
pub(crate) setter: Option<Rc<dyn FieldSetter<FD, FDT>>>,
|
||||||
pub(crate) parse_fn: Option<Box<dyn ParseFn<C::ReturnType, FDT>>>,
|
pub(crate) parse_fn: Option<Box<dyn ParseFn<C::ReturnType, FDT>>>,
|
||||||
pub(crate) unparse_fn: Option<Box<dyn UnparseFn<C::ReturnType, FDT>>>,
|
pub(crate) unparse_fn: Option<Box<dyn UnparseFn<C::ReturnType, FDT>>>,
|
||||||
pub(crate) validation_fn: Option<Rc<dyn ValidationFn<FD>>>,
|
pub(crate) validation_fn: Option<Rc<dyn ValidationFn<FD>>>,
|
||||||
pub(crate) style_attributes: Vec<FS::StylingAttributes>,
|
pub(crate) style_attributes: Vec<<FD::Style as FormStyle>::StylingAttributes>,
|
||||||
pub data: C,
|
pub data: C,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> ControlBuilder<FD, FS, C, FDT> {
|
impl<FD: FormToolData, C: ControlData, FDT> ControlBuilder<FD, C, FDT> {
|
||||||
/// Creates a new [`ControlBuilder`] with the given [`ControlData`].
|
/// Creates a new [`ControlBuilder`] with the given [`ControlData`].
|
||||||
pub(crate) fn new(data: C) -> Self {
|
pub(crate) fn new(data: C) -> Self {
|
||||||
ControlBuilder {
|
ControlBuilder {
|
||||||
@ -188,7 +190,7 @@ impl<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> ControlBuilder<FD, FS
|
|||||||
/// Builds the builder into the data needed to render the control.
|
/// Builds the builder into the data needed to render the control.
|
||||||
///
|
///
|
||||||
/// This fails if a required field was not specified.
|
/// This fails if a required field was not specified.
|
||||||
pub(crate) fn build(self) -> Result<BuiltControlData<FD, FS, C, FDT>, ControlBuildError> {
|
pub(crate) fn build(self) -> Result<BuiltControlData<FD, C, FDT>, ControlBuildError> {
|
||||||
let getter = match self.getter {
|
let getter = match self.getter {
|
||||||
Some(getter) => getter,
|
Some(getter) => getter,
|
||||||
None => return Err(ControlBuildError::MissingGetter),
|
None => return Err(ControlBuildError::MissingGetter),
|
||||||
@ -257,16 +259,15 @@ impl<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> ControlBuilder<FD, FS
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a styling attribute to this control.
|
/// Adds a styling attribute to this control.
|
||||||
pub fn style(mut self, attribute: FS::StylingAttributes) -> Self {
|
pub fn style(mut self, attribute: <FD::Style as FormStyle>::StylingAttributes) -> Self {
|
||||||
self.style_attributes.push(attribute);
|
self.style_attributes.push(attribute);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD, FS, C, FDT> ControlBuilder<FD, FS, C, FDT>
|
impl<FD, C, FDT> ControlBuilder<FD, C, FDT>
|
||||||
where
|
where
|
||||||
FD: FormToolData,
|
FD: FormToolData,
|
||||||
FS: FormStyle,
|
|
||||||
C: ControlData,
|
C: ControlData,
|
||||||
FDT: TryFrom<<C as ControlData>::ReturnType>,
|
FDT: TryFrom<<C as ControlData>::ReturnType>,
|
||||||
<FDT as TryFrom<<C as ControlData>::ReturnType>>::Error: ToString,
|
<FDT as TryFrom<<C as ControlData>::ReturnType>>::Error: ToString,
|
||||||
@ -289,10 +290,9 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD, FS, C, FDT> ControlBuilder<FD, FS, C, FDT>
|
impl<FD, C, FDT> ControlBuilder<FD, C, FDT>
|
||||||
where
|
where
|
||||||
FD: FormToolData,
|
FD: FormToolData,
|
||||||
FS: FormStyle,
|
|
||||||
C: ControlData<ReturnType = String>,
|
C: ControlData<ReturnType = String>,
|
||||||
FDT: FromStr + ToString,
|
FDT: FromStr + ToString,
|
||||||
<FDT as FromStr>::Err: ToString,
|
<FDT as FromStr>::Err: ToString,
|
||||||
@ -333,7 +333,7 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, C: ValidatedControlData, FDT> ControlBuilder<FD, FS, C, FDT> {
|
impl<FD: FormToolData, C: ValidatedControlData, FDT> ControlBuilder<FD, C, FDT> {
|
||||||
/// Sets the validation function for this control
|
/// Sets the validation function for this control
|
||||||
///
|
///
|
||||||
/// This allows you to check if the parsed value is a valid value.
|
/// This allows you to check if the parsed value is a valid value.
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
use leptos::{Signal, View};
|
use super::{
|
||||||
|
BuilderFn, ControlRenderData, GetterVanityControlData, VanityControlBuilder, VanityControlData,
|
||||||
use super::{ControlRenderData, GetterVanityControlData, VanityControlBuilder, VanityControlData};
|
};
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct OutputData;
|
pub struct OutputData;
|
||||||
@ -17,12 +18,10 @@ impl VanityControlData for OutputData {
|
|||||||
}
|
}
|
||||||
impl GetterVanityControlData for OutputData {}
|
impl GetterVanityControlData for OutputData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn output(
|
pub fn output(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<VanityControlBuilder<FD, OutputData>, FD::Context>,
|
||||||
VanityControlBuilder<FD, FS, OutputData>,
|
|
||||||
) -> VanityControlBuilder<FD, FS, OutputData>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_vanity(builder)
|
self.new_vanity(builder)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{Signal, View};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct RadioButtonsData {
|
pub struct RadioButtonsData {
|
||||||
@ -25,18 +24,16 @@ impl ControlData for RadioButtonsData {
|
|||||||
}
|
}
|
||||||
impl ValidatedControlData for RadioButtonsData {}
|
impl ValidatedControlData for RadioButtonsData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn radio_buttons<FDT: Clone + PartialEq + 'static>(
|
pub fn radio_buttons<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, RadioButtonsData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, RadioButtonsData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, RadioButtonsData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, RadioButtonsData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, RadioButtonsData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
use leptos::{Signal, View};
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
@ -27,18 +27,16 @@ impl ControlData for SelectData {
|
|||||||
}
|
}
|
||||||
impl ValidatedControlData for SelectData {}
|
impl ValidatedControlData for SelectData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn select<FDT: Clone + PartialEq + 'static>(
|
pub fn select<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, SelectData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, SelectData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, SelectData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, SelectData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, SelectData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
use std::ops::RangeInclusive;
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData};
|
||||||
|
|
||||||
use leptos::{Signal, View};
|
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct SliderData {
|
pub struct SliderData {
|
||||||
@ -38,18 +36,16 @@ impl ControlData for SliderData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn slider<FDT: Clone + PartialEq + 'static>(
|
pub fn slider<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, SliderData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, SliderData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, SliderData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, SliderData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, SliderData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{prelude::Signal, View};
|
use super::{BuilderFn, ControlRenderData, VanityControlBuilder, VanityControlData};
|
||||||
|
|
||||||
use super::{ControlRenderData, VanityControlBuilder, VanityControlData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{prelude::Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct SpacerData {
|
pub struct SpacerData {
|
||||||
@ -18,18 +17,16 @@ impl VanityControlData for SpacerData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn spacer(
|
pub fn spacer(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<VanityControlBuilder<FD, SpacerData>, FD::Context>,
|
||||||
VanityControlBuilder<FD, FS, SpacerData>,
|
|
||||||
) -> VanityControlBuilder<FD, FS, SpacerData>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_vanity(builder)
|
self.new_vanity(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> VanityControlBuilder<FD, FS, SpacerData> {
|
impl<FD: FormToolData> VanityControlBuilder<FD, SpacerData> {
|
||||||
pub fn height(mut self, height: impl ToString) -> Self {
|
pub fn height(mut self, height: impl ToString) -> Self {
|
||||||
self.data.height = Some(height.to_string());
|
self.data.height = Some(height.to_string());
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,9 +1,7 @@
|
|||||||
use std::ops::RangeInclusive;
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
||||||
|
|
||||||
use leptos::{Signal, View};
|
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
use std::ops::RangeInclusive;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct StepperData {
|
pub struct StepperData {
|
||||||
@ -29,18 +27,16 @@ impl ControlData for StepperData {
|
|||||||
}
|
}
|
||||||
impl ValidatedControlData for StepperData {}
|
impl ValidatedControlData for StepperData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn stepper<FDT: Clone + PartialEq + 'static>(
|
pub fn stepper<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, StepperData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, StepperData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, StepperData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, StepperData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, StepperData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{prelude::Signal, View};
|
use super::{BuilderFn, ControlRenderData, VanityControlBuilder, VanityControlData};
|
||||||
|
|
||||||
use super::{ControlRenderData, VanityControlBuilder, VanityControlData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{prelude::Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)]
|
||||||
pub struct SubmitData {
|
pub struct SubmitData {
|
||||||
@ -18,18 +17,16 @@ impl VanityControlData for SubmitData {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn submit(
|
pub fn submit(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<VanityControlBuilder<FD, SubmitData>, FD::Context>,
|
||||||
VanityControlBuilder<FD, FS, SubmitData>,
|
|
||||||
) -> VanityControlBuilder<FD, FS, SubmitData>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_vanity(builder)
|
self.new_vanity(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> VanityControlBuilder<FD, FS, SubmitData> {
|
impl<FD: FormToolData> VanityControlBuilder<FD, SubmitData> {
|
||||||
pub fn text(mut self, text: impl ToString) -> Self {
|
pub fn text(mut self, text: impl ToString) -> Self {
|
||||||
self.data.text = text.to_string();
|
self.data.text = text.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use super::{ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
use leptos::{Signal, View};
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
@ -23,18 +23,16 @@ impl ControlData for TextAreaData {
|
|||||||
}
|
}
|
||||||
impl ValidatedControlData for TextAreaData {}
|
impl ValidatedControlData for TextAreaData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn text_area<FDT: Clone + PartialEq + 'static>(
|
pub fn text_area<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, TextAreaData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, TextAreaData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, TextAreaData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, TextAreaData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, TextAreaData, FDT> {
|
||||||
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
|
||||||
|
|||||||
@ -1,7 +1,6 @@
|
|||||||
use leptos::{Signal, View};
|
use super::{BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
||||||
|
|
||||||
use super::{ControlBuilder, ControlData, ControlRenderData, ValidatedControlData};
|
|
||||||
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
|
||||||
|
use leptos::{Signal, View};
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub struct TextInputData {
|
pub struct TextInputData {
|
||||||
@ -39,18 +38,16 @@ impl ControlData for TextInputData {
|
|||||||
}
|
}
|
||||||
impl ValidatedControlData for TextInputData {}
|
impl ValidatedControlData for TextInputData {}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
pub fn text_input<FDT: Clone + PartialEq + 'static>(
|
pub fn text_input<FDT: Clone + PartialEq + 'static>(
|
||||||
self,
|
self,
|
||||||
builder: impl Fn(
|
builder: impl BuilderFn<ControlBuilder<FD, TextInputData, FDT>, FD::Context>,
|
||||||
ControlBuilder<FD, FS, TextInputData, FDT>,
|
|
||||||
) -> ControlBuilder<FD, FS, TextInputData, FDT>,
|
|
||||||
) -> Self {
|
) -> Self {
|
||||||
self.new_control(builder)
|
self.new_control(builder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle, FDT> ControlBuilder<FD, FS, TextInputData, FDT> {
|
impl<FD: FormToolData, FDT> ControlBuilder<FD, TextInputData, FDT> {
|
||||||
pub fn named(mut self, control_name: impl ToString) -> Self {
|
pub fn named(mut self, control_name: impl ToString) -> Self {
|
||||||
self.data.name = control_name.to_string();
|
self.data.name = control_name.to_string();
|
||||||
self
|
self
|
||||||
|
|||||||
34
src/form.rs
34
src/form.rs
@ -40,15 +40,16 @@ pub struct Form<FD: FormToolData> {
|
|||||||
|
|
||||||
impl<FD: FormToolData> Form<FD> {
|
impl<FD: FormToolData> Form<FD> {
|
||||||
/// Gets the [`Validator`] for this form.
|
/// Gets the [`Validator`] for this form.
|
||||||
pub fn validator(self) -> FormValidator<FD> {
|
pub fn validator(&self) -> FormValidator<FD> {
|
||||||
FormValidator {
|
FormValidator {
|
||||||
validations: self.validations,
|
validations: self.validations.clone(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates the [`ToolFormData`], returning the result
|
/// Validates the [`ToolFormData`], returning the result
|
||||||
pub fn validate(&self) -> Result<(), String> {
|
pub fn validate(&self) -> Result<(), String> {
|
||||||
self.fd.get_untracked().validate()
|
let validator = self.validator();
|
||||||
|
validator.validate(&self.fd.get_untracked())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the view associated with this [`Form`].
|
/// Gets the view associated with this [`Form`].
|
||||||
@ -80,6 +81,7 @@ impl<FD: FormToolData> IntoView for Form<FD> {
|
|||||||
/// to physically lay out a form, and how that data should be parsed and validated.
|
/// to physically lay out a form, and how that data should be parsed and validated.
|
||||||
pub trait FormToolData: Clone + 'static {
|
pub trait FormToolData: Clone + 'static {
|
||||||
type Style: FormStyle;
|
type Style: FormStyle;
|
||||||
|
type Context: 'static;
|
||||||
|
|
||||||
/// Defines how the form should be layed out and how the data should be parsed and validated.
|
/// Defines how the form should be layed out and how the data should be parsed and validated.
|
||||||
///
|
///
|
||||||
@ -88,7 +90,7 @@ pub trait FormToolData: Clone + 'static {
|
|||||||
/// Uses the given form builder to specify what fields should be present
|
/// Uses the given form builder to specify what fields should be present
|
||||||
/// in the form, what properties those fields should have, and how that
|
/// in the form, what properties those fields should have, and how that
|
||||||
/// data should be parsed and checked.
|
/// data should be parsed and checked.
|
||||||
fn build_form(fb: FormBuilder<Self, Self::Style>) -> FormBuilder<Self, Self::Style>;
|
fn build_form(fb: FormBuilder<Self>) -> FormBuilder<Self>;
|
||||||
|
|
||||||
/// Constructs a [`Form`] for this [`FormToolData`] type.
|
/// Constructs a [`Form`] for this [`FormToolData`] type.
|
||||||
///
|
///
|
||||||
@ -96,8 +98,13 @@ pub trait FormToolData: Clone + 'static {
|
|||||||
/// [`Form`](leptos_router::Form)
|
/// [`Form`](leptos_router::Form)
|
||||||
/// component. Call [`get_action_form`]\() to get the
|
/// component. Call [`get_action_form`]\() to get the
|
||||||
/// [`ActionForm`](leptos_router::ActionForm) version.
|
/// [`ActionForm`](leptos_router::ActionForm) version.
|
||||||
fn get_form(self, action: impl ToString, style: Self::Style) -> Form<Self> {
|
fn get_form(
|
||||||
let builder = FormBuilder::new();
|
self,
|
||||||
|
action: impl ToString,
|
||||||
|
style: Self::Style,
|
||||||
|
context: Self::Context,
|
||||||
|
) -> Form<Self> {
|
||||||
|
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_plain_form(action.to_string(), self, style)
|
||||||
}
|
}
|
||||||
@ -112,13 +119,14 @@ pub trait FormToolData: Clone + 'static {
|
|||||||
self,
|
self,
|
||||||
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
|
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
|
||||||
style: Self::Style,
|
style: Self::Style,
|
||||||
|
context: Self::Context,
|
||||||
) -> Form<Self>
|
) -> Form<Self>
|
||||||
where
|
where
|
||||||
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>,
|
||||||
{
|
{
|
||||||
let builder = FormBuilder::new();
|
let builder = FormBuilder::new(context);
|
||||||
let builder = Self::build_form(builder);
|
let builder = Self::build_form(builder);
|
||||||
builder.build_action_form(action, self, style)
|
builder.build_action_form(action, self, style)
|
||||||
}
|
}
|
||||||
@ -131,18 +139,18 @@ pub trait FormToolData: Clone + 'static {
|
|||||||
///
|
///
|
||||||
/// However, the code to render the views are not configured out, it
|
/// 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.
|
/// simply doesn't run, so the view needs to compile even on the server.
|
||||||
fn get_validator() -> FormValidator<Self> {
|
fn get_validator(context: Self::Context) -> FormValidator<Self> {
|
||||||
let builder = FormBuilder::new();
|
let builder = FormBuilder::new(context);
|
||||||
let builder = Self::build_form(builder);
|
let builder = Self::build_form(builder);
|
||||||
builder.validator()
|
builder.validator()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Validates this [`FormToolData`] struct.
|
/// Validates this [`FormToolData`] struct.
|
||||||
///
|
///
|
||||||
/// This is shorthand for creating a validator with [`get_validator`]\()
|
/// This is shorthand for creating a validator with [`get_validator`]
|
||||||
/// and then calling `validator.validate(&self)`.
|
/// and then calling `validator.validate(&self, context)`.
|
||||||
fn validate(&self) -> Result<(), String> {
|
fn validate(&self, context: Self::Context) -> Result<(), String> {
|
||||||
let validator = Self::get_validator();
|
let validator = Self::get_validator(context);
|
||||||
validator.validate(self)
|
validator.validate(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,8 +1,8 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
controls::{
|
controls::{
|
||||||
BuiltControlData, BuiltVanityControlData, ControlBuilder, ControlData, ControlRenderData,
|
BuilderFn, BuiltControlData, BuiltVanityControlData, ControlBuilder, ControlData,
|
||||||
FieldSetter, ParseFn, RenderFn, ValidationCb, ValidationFn, VanityControlBuilder,
|
ControlRenderData, FieldSetter, ParseFn, RenderFn, ValidationCb, ValidationFn,
|
||||||
VanityControlData,
|
VanityControlBuilder, VanityControlData,
|
||||||
},
|
},
|
||||||
form::{Form, FormToolData, FormValidator},
|
form::{Form, FormToolData, FormValidator},
|
||||||
styles::FormStyle,
|
styles::FormStyle,
|
||||||
@ -16,49 +16,70 @@ use serde::de::DeserializeOwned;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use web_sys::{FormData, SubmitEvent};
|
use web_sys::{FormData, SubmitEvent};
|
||||||
|
|
||||||
|
// TODO: FS, and CX may be uncessisary, as FS is the same as FD::Style
|
||||||
|
// and CX is the same as FD::Context.
|
||||||
|
|
||||||
/// A builder for laying out forms.
|
/// A builder for laying out forms.
|
||||||
///
|
///
|
||||||
/// This builder allows you to specify what components should make up the form.
|
/// This builder allows you to specify what components should make up the form.
|
||||||
pub struct FormBuilder<FD: FormToolData, FS: FormStyle> {
|
///
|
||||||
|
/// ### Type Parameters
|
||||||
|
/// - `FD`: FormToolData - Your form data
|
||||||
|
/// - `FS`: FormStyle - The form style you are using
|
||||||
|
/// - `CX`: Context - A user defined context that you are rendering the form in
|
||||||
|
pub struct FormBuilder<FD: FormToolData> {
|
||||||
|
pub(crate) cx: Rc<FD::Context>,
|
||||||
/// The list of [`ValidationFn`]s.
|
/// The list of [`ValidationFn`]s.
|
||||||
pub(crate) validations: Vec<Rc<dyn ValidationFn<FD>>>,
|
pub(crate) validations: Vec<Rc<dyn ValidationFn<FD>>>,
|
||||||
/// The list of functions that will render the form.
|
/// The list of functions that will render the form.
|
||||||
pub(crate) render_fns: Vec<Box<dyn RenderFn<FS, FD>>>,
|
pub(crate) render_fns: Vec<Box<dyn RenderFn<FD::Style, FD>>>,
|
||||||
/// The list of styling attributes applied on the form level
|
/// The list of styling attributes applied on the form level
|
||||||
pub(crate) styles: Vec<FS::StylingAttributes>,
|
pub(crate) styles: Vec<<FD::Style as FormStyle>::StylingAttributes>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
impl<FD: FormToolData> FormBuilder<FD> {
|
||||||
/// Creates a new [`FormBuilder`]
|
/// Creates a new [`FormBuilder`]
|
||||||
pub(crate) fn new() -> FormBuilder<FD, FS> {
|
pub(crate) fn new(cx: FD::Context) -> Self {
|
||||||
FormBuilder {
|
FormBuilder {
|
||||||
|
cx: Rc::new(cx),
|
||||||
validations: Vec::new(),
|
validations: Vec::new(),
|
||||||
render_fns: Vec::new(),
|
render_fns: Vec::new(),
|
||||||
styles: Vec::new(),
|
styles: Vec::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn style(mut self, style: FS::StylingAttributes) -> Self {
|
/// Creates a new [`FormBuilder`] with the given Rc'ed context, for
|
||||||
|
//// building a form group.
|
||||||
|
pub(crate) fn new_group(cx: Rc<FD::Context>) -> Self {
|
||||||
|
FormBuilder {
|
||||||
|
cx,
|
||||||
|
validations: Vec::new(),
|
||||||
|
render_fns: Vec::new(),
|
||||||
|
styles: Vec::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn style(mut self, style: <FD::Style as FormStyle>::StylingAttributes) -> Self {
|
||||||
self.styles.push(style);
|
self.styles.push(style);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_vanity<C: VanityControlData + Default>(
|
pub(crate) fn new_vanity<C: VanityControlData + Default>(
|
||||||
mut self,
|
mut self,
|
||||||
builder: impl Fn(VanityControlBuilder<FD, FS, C>) -> VanityControlBuilder<FD, FS, C>,
|
builder: impl BuilderFn<VanityControlBuilder<FD, C>, FD::Context>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let vanity_builder = VanityControlBuilder::new(C::default());
|
let vanity_builder = VanityControlBuilder::new(C::default());
|
||||||
let control = builder(vanity_builder);
|
let control = builder(vanity_builder, &self.cx);
|
||||||
self.add_vanity(control);
|
self.add_vanity(control);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn new_control<C: ControlData + Default, FDT: Clone + PartialEq + 'static>(
|
pub(crate) fn new_control<C: ControlData + Default, FDT: Clone + PartialEq + 'static>(
|
||||||
mut self,
|
mut self,
|
||||||
builder: impl Fn(ControlBuilder<FD, FS, C, FDT>) -> ControlBuilder<FD, FS, C, FDT>,
|
builder: impl BuilderFn<ControlBuilder<FD, C, FDT>, FD::Context>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let control_builder = ControlBuilder::new(C::default());
|
let control_builder = ControlBuilder::new(C::default());
|
||||||
let control = builder(control_builder);
|
let control = builder(control_builder, &self.cx);
|
||||||
self.add_control(control);
|
self.add_control(control);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
@ -66,14 +87,14 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
// TODO: test this from a user context. A user adding a custom defined component.
|
// TODO: test this from a user context. A user adding a custom defined component.
|
||||||
pub fn add_vanity<C: VanityControlData>(
|
pub fn add_vanity<C: VanityControlData>(
|
||||||
&mut self,
|
&mut self,
|
||||||
vanity_control: VanityControlBuilder<FD, FS, C>,
|
vanity_control: VanityControlBuilder<FD, C>,
|
||||||
) {
|
) {
|
||||||
let BuiltVanityControlData {
|
let BuiltVanityControlData {
|
||||||
render_data,
|
render_data,
|
||||||
getter,
|
getter,
|
||||||
} = vanity_control.build();
|
} = vanity_control.build();
|
||||||
|
|
||||||
let render_fn = move |fs: &FS, fd: RwSignal<FD>| {
|
let render_fn = move |fs: &FD::Style, fd: RwSignal<FD>| {
|
||||||
let value_getter = getter.map(|getter| (move || getter(fd.get())).into_signal());
|
let value_getter = getter.map(|getter| (move || getter(fd.get())).into_signal());
|
||||||
let view = VanityControlData::build_control(fs, render_data, value_getter);
|
let view = VanityControlData::build_control(fs, render_data, value_getter);
|
||||||
(view, None)
|
(view, None)
|
||||||
@ -85,7 +106,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
// TODO: test this from a user context. A user adding a custom defined component.
|
// TODO: test this from a user context. A user adding a custom defined component.
|
||||||
pub fn add_control<C: ControlData, FDT: Clone + PartialEq + 'static>(
|
pub fn add_control<C: ControlData, FDT: Clone + PartialEq + 'static>(
|
||||||
&mut self,
|
&mut self,
|
||||||
control: ControlBuilder<FD, FS, C, FDT>,
|
control: ControlBuilder<FD, C, FDT>,
|
||||||
) {
|
) {
|
||||||
let built_control_data = match control.build() {
|
let built_control_data = match control.build() {
|
||||||
Ok(c) => c,
|
Ok(c) => c,
|
||||||
@ -96,7 +117,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
self.validations.push(validation_fn.clone());
|
self.validations.push(validation_fn.clone());
|
||||||
}
|
}
|
||||||
|
|
||||||
let render_fn = move |fs: &FS, fd: RwSignal<FD>| {
|
let render_fn = move |fs: &FD::Style, fd: RwSignal<FD>| {
|
||||||
let (view, cb) = Self::build_control_view(fd, fs, built_control_data);
|
let (view, cb) = Self::build_control_view(fd, fs, built_control_data);
|
||||||
(view, Some(cb))
|
(view, Some(cb))
|
||||||
};
|
};
|
||||||
@ -106,8 +127,8 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
|
|
||||||
fn build_control_view<C: ControlData, FDT: 'static>(
|
fn build_control_view<C: ControlData, FDT: 'static>(
|
||||||
fd: RwSignal<FD>,
|
fd: RwSignal<FD>,
|
||||||
fs: &FS,
|
fs: &FD::Style,
|
||||||
control_data: BuiltControlData<FD, FS, C, FDT>,
|
control_data: BuiltControlData<FD, C, FDT>,
|
||||||
) -> (View, Box<dyn ValidationCb>) {
|
) -> (View, Box<dyn ValidationCb>) {
|
||||||
let BuiltControlData {
|
let BuiltControlData {
|
||||||
render_data,
|
render_data,
|
||||||
@ -204,7 +225,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
self,
|
self,
|
||||||
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
|
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
|
||||||
fd: FD,
|
fd: FD,
|
||||||
fs: FS,
|
fs: FD::Style,
|
||||||
) -> Form<FD>
|
) -> Form<FD>
|
||||||
where
|
where
|
||||||
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
|
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
|
||||||
@ -249,7 +270,7 @@ impl<FD: FormToolData, FS: FormStyle> FormBuilder<FD, FS> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn build_plain_form(self, url: String, fd: FD, fs: FS) -> Form<FD> {
|
pub(crate) fn build_plain_form(self, url: String, fd: FD, fs: FD::Style) -> Form<FD> {
|
||||||
let fd = create_rw_signal(fd);
|
let fd = create_rw_signal(fd);
|
||||||
|
|
||||||
let (views, validation_cbs): (Vec<_>, Vec<_>) = self
|
let (views, validation_cbs): (Vec<_>, Vec<_>) = self
|
||||||
|
|||||||
@ -365,7 +365,7 @@ impl FormStyle for GridFormStyle {
|
|||||||
let action = control.data.action.clone();
|
let action = control.data.action.clone();
|
||||||
let on_click = move |ev: MouseEvent| {
|
let on_click = move |ev: MouseEvent| {
|
||||||
if let Some(action) = action.clone() {
|
if let Some(action) = action.clone() {
|
||||||
data_signal.update(|fd| action(ev, fd));
|
action(ev, data_signal)
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user