remove the FS and CX generics

This commit is contained in:
Mitchell Marino 2024-06-12 18:44:43 -05:00
parent e371ff748b
commit fac8e515f6
19 changed files with 114 additions and 103 deletions

View File

@ -1,12 +1,11 @@
use super::ControlRenderData;
use super::{BuilderFn, ControlRenderData};
use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle};
use leptos::RwSignal;
use std::rc::Rc;
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(crate) text: String,
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, CX: 'static> FormBuilder<FD, FS, CX> {
pub fn button(
mut self,
builder: impl Fn(ButtonBuilder<FD, FS>) -> ButtonBuilder<FD, FS>,
) -> Self {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn button(mut self, builder: impl BuilderFn<ButtonBuilder<FD>, FD::Context>) -> Self {
let button_builder = ButtonBuilder::new();
let control = builder(button_builder);
let control = builder(button_builder, &self.cx);
let render_data = ControlRenderData {
data: control.data,
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);
(view, None)
};
@ -43,13 +47,12 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
}
}
#[derive(Clone)]
pub struct ButtonBuilder<FD: FormToolData, FS: FormStyle> {
pub(crate) styles: Vec<FS::StylingAttributes>,
pub struct ButtonBuilder<FD: FormToolData> {
pub(crate) styles: Vec<<FD::Style as FormStyle>::StylingAttributes>,
pub(crate) data: ButtonData<FD>,
}
impl<FD: FormToolData, FS: FormStyle> ButtonBuilder<FD, FS> {
impl<FD: FormToolData> ButtonBuilder<FD> {
fn new() -> Self {
ButtonBuilder {
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
}
@ -67,7 +70,7 @@ impl<FD: FormToolData, FS: FormStyle> ButtonBuilder<FD, FS> {
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
}

View File

@ -22,16 +22,16 @@ impl ControlData for CheckboxData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn checkbox<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, CheckboxData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, CheckboxData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -1,11 +1,11 @@
use super::{BuilderFn, ControlBuilder, ControlData};
use crate::{styles::FormStyle, FormBuilder, FormToolData};
use crate::{FormBuilder, FormToolData};
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn custom<CC: ControlData, FDT: Clone + PartialEq + 'static>(
mut self,
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 {
let control_builder = ControlBuilder::new(control_data);
let control = builder(control_builder);
@ -15,7 +15,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
pub fn custom_default<CC: Default + ControlData, FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, CC, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, CC, FDT>, FD::Context>,
) -> Self {
self.new_control(builder)
}

View File

@ -1,13 +1,11 @@
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};
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
pub fn group(
mut self,
builder: impl Fn(FormBuilder<FD, FS, CX>) -> FormBuilder<FD, FS, CX>,
) -> Self {
let mut group_builder = FormBuilder::new(self.cx);
impl<FD: FormToolData> FormBuilder<FD> {
pub fn group(mut self, builder: impl Fn(FormBuilder<FD>) -> FormBuilder<FD>) -> Self {
let mut group_builder = FormBuilder::new_group(self.cx);
group_builder = builder(group_builder);
// Take context back
@ -17,7 +15,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
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
.render_fns
.into_iter()

View File

@ -17,16 +17,16 @@ impl VanityControlData for HeadingData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn heading(
self,
builder: impl BuilderFn<VanityControlBuilder<FD, FS, HeadingData>, CX>,
builder: impl BuilderFn<VanityControlBuilder<FD, HeadingData>, FD::Context>,
) -> Self {
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 {
self.data.title = title.to_string();
self

View File

@ -19,10 +19,10 @@ impl ControlData for HiddenData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn hidden<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, HiddenData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, HiddenData, FDT>, FD::Context>,
) -> Self {
self.new_control(builder)
}

View File

@ -77,18 +77,18 @@ pub struct ControlRenderData<FS: FormStyle + ?Sized, C: ?Sized> {
}
/// The data needed to render a read-only control of type `C`.
pub struct VanityControlBuilder<FD: FormToolData, FS: FormStyle, C: VanityControlData> {
pub(crate) style_attributes: Vec<FS::StylingAttributes>,
pub struct VanityControlBuilder<FD: FormToolData, C: VanityControlData> {
pub(crate) style_attributes: Vec<<FD::Style as FormStyle>::StylingAttributes>,
pub(crate) data: C,
pub(crate) getter: Option<Rc<dyn FieldGetter<FD, String>>>,
}
pub(crate) struct BuiltVanityControlData<FD: FormToolData, FS: FormStyle, C: VanityControlData> {
pub(crate) render_data: ControlRenderData<FS, C>,
pub(crate) struct BuiltVanityControlData<FD: FormToolData, C: VanityControlData> {
pub(crate) render_data: ControlRenderData<FD::Style, C>,
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`].
pub(crate) fn new(data: C) -> Self {
VanityControlBuilder {
@ -99,7 +99,7 @@ impl<FD: FormToolData, FS: FormStyle, C: VanityControlData> VanityControlBuilder
}
/// 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 {
render_data: ControlRenderData {
data: self.data,
@ -110,13 +110,13 @@ impl<FD: FormToolData, FS: FormStyle, C: VanityControlData> VanityControlBuilder
}
/// 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
}
}
impl<FD: FormToolData, FS: FormStyle, C: GetterVanityControlData> VanityControlBuilder<FD, FS, C> {
impl<FD: FormToolData, C: GetterVanityControlData> VanityControlBuilder<FD, C> {
/// Sets the getter function.
///
/// This function can get a string from the form data to be displayed
@ -153,8 +153,8 @@ impl Display for ControlBuildError {
}
/// The data returned fomr a control's build function.
pub(crate) struct BuiltControlData<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> {
pub(crate) render_data: ControlRenderData<FS, C>,
pub(crate) struct BuiltControlData<FD: FormToolData, C: ControlData, FDT> {
pub(crate) render_data: ControlRenderData<FD::Style, C>,
pub(crate) getter: Rc<dyn FieldGetter<FD, FDT>>,
pub(crate) setter: Rc<dyn FieldSetter<FD, FDT>>,
pub(crate) parse_fn: Box<dyn ParseFn<C::ReturnType, FDT>>,
@ -163,17 +163,17 @@ pub(crate) struct BuiltControlData<FD: FormToolData, FS: FormStyle, C: ControlDa
}
/// 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) setter: Option<Rc<dyn FieldSetter<FD, 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) 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,
}
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`].
pub(crate) fn new(data: C) -> Self {
ControlBuilder {
@ -190,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.
///
/// 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 {
Some(getter) => getter,
None => return Err(ControlBuildError::MissingGetter),
@ -259,16 +259,15 @@ impl<FD: FormToolData, FS: FormStyle, C: ControlData, FDT> ControlBuilder<FD, FS
}
/// 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
}
}
impl<FD, FS, C, FDT> ControlBuilder<FD, FS, C, FDT>
impl<FD, C, FDT> ControlBuilder<FD, C, FDT>
where
FD: FormToolData,
FS: FormStyle,
C: ControlData,
FDT: TryFrom<<C as ControlData>::ReturnType>,
<FDT as TryFrom<<C as ControlData>::ReturnType>>::Error: ToString,
@ -291,10 +290,9 @@ where
}
}
impl<FD, FS, C, FDT> ControlBuilder<FD, FS, C, FDT>
impl<FD, C, FDT> ControlBuilder<FD, C, FDT>
where
FD: FormToolData,
FS: FormStyle,
C: ControlData<ReturnType = String>,
FDT: FromStr + ToString,
<FDT as FromStr>::Err: ToString,
@ -335,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
///
/// This allows you to check if the parsed value is a valid value.

View File

@ -18,10 +18,10 @@ impl VanityControlData for OutputData {
}
impl GetterVanityControlData for OutputData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn output(
self,
builder: impl BuilderFn<VanityControlBuilder<FD, FS, OutputData>, CX>,
builder: impl BuilderFn<VanityControlBuilder<FD, OutputData>, FD::Context>,
) -> Self {
self.new_vanity(builder)
}

View File

@ -24,16 +24,16 @@ impl ControlData for RadioButtonsData {
}
impl ValidatedControlData for RadioButtonsData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn radio_buttons<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, RadioButtonsData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, RadioButtonsData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -27,16 +27,16 @@ impl ControlData for SelectData {
}
impl ValidatedControlData for SelectData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn select<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, SelectData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, SelectData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -36,16 +36,16 @@ impl ControlData for SliderData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn slider<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, SliderData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, SliderData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -17,16 +17,16 @@ impl VanityControlData for SpacerData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn spacer(
self,
builder: impl BuilderFn<VanityControlBuilder<FD, FS, SpacerData>, CX>,
builder: impl BuilderFn<VanityControlBuilder<FD, SpacerData>, FD::Context>,
) -> Self {
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 {
self.data.height = Some(height.to_string());
self

View File

@ -27,16 +27,16 @@ impl ControlData for StepperData {
}
impl ValidatedControlData for StepperData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn stepper<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, StepperData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, StepperData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -17,16 +17,16 @@ impl VanityControlData for SubmitData {
}
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn submit(
self,
builder: impl BuilderFn<VanityControlBuilder<FD, FS, SubmitData>, CX>,
builder: impl BuilderFn<VanityControlBuilder<FD, SubmitData>, FD::Context>,
) -> Self {
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 {
self.data.text = text.to_string();
self

View File

@ -23,16 +23,16 @@ impl ControlData for TextAreaData {
}
impl ValidatedControlData for TextAreaData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn text_area<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, TextAreaData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, TextAreaData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.placeholder = Some(placeholder.to_string());
self

View File

@ -38,16 +38,16 @@ impl ControlData for TextInputData {
}
impl ValidatedControlData for TextInputData {}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
pub fn text_input<FDT: Clone + PartialEq + 'static>(
self,
builder: impl BuilderFn<ControlBuilder<FD, FS, TextInputData, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, TextInputData, FDT>, FD::Context>,
) -> Self {
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 {
self.data.name = control_name.to_string();
self

View File

@ -90,9 +90,7 @@ pub trait FormToolData: Clone + 'static {
/// Uses the given form builder to specify what fields should be present
/// in the form, what properties those fields should have, and how that
/// data should be parsed and checked.
fn build_form(
fb: FormBuilder<Self, Self::Style, Self::Context>,
) -> FormBuilder<Self, Self::Style, Self::Context>;
fn build_form(fb: FormBuilder<Self>) -> FormBuilder<Self>;
/// Constructs a [`Form`] for this [`FormToolData`] type.
///

View File

@ -16,6 +16,9 @@ use serde::de::DeserializeOwned;
use std::rc::Rc;
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.
///
/// This builder allows you to specify what components should make up the form.
@ -24,19 +27,30 @@ use web_sys::{FormData, SubmitEvent};
/// - `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, FS: FormStyle, CX: 'static> {
pub(crate) cx: CX,
pub struct FormBuilder<FD: FormToolData> {
pub(crate) cx: Rc<FD::Context>,
/// The list of [`ValidationFn`]s.
pub(crate) validations: Vec<Rc<dyn ValidationFn<FD>>>,
/// 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
pub(crate) styles: Vec<FS::StylingAttributes>,
pub(crate) styles: Vec<<FD::Style as FormStyle>::StylingAttributes>,
}
impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
impl<FD: FormToolData> FormBuilder<FD> {
/// Creates a new [`FormBuilder`]
pub(crate) fn new(cx: CX) -> Self {
pub(crate) fn new(cx: FD::Context) -> Self {
FormBuilder {
cx: Rc::new(cx),
validations: Vec::new(),
render_fns: Vec::new(),
styles: Vec::new(),
}
}
/// 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(),
@ -45,14 +59,14 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
}
}
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
}
pub(crate) fn new_vanity<C: VanityControlData + Default>(
mut self,
builder: impl BuilderFn<VanityControlBuilder<FD, FS, C>, CX>,
builder: impl BuilderFn<VanityControlBuilder<FD, C>, FD::Context>,
) -> Self {
let vanity_builder = VanityControlBuilder::new(C::default());
let control = builder(vanity_builder, &self.cx);
@ -62,7 +76,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
pub(crate) fn new_control<C: ControlData + Default, FDT: Clone + PartialEq + 'static>(
mut self,
builder: impl BuilderFn<ControlBuilder<FD, FS, C, FDT>, CX>,
builder: impl BuilderFn<ControlBuilder<FD, C, FDT>, FD::Context>,
) -> Self {
let control_builder = ControlBuilder::new(C::default());
let control = builder(control_builder, &self.cx);
@ -73,14 +87,14 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
// TODO: test this from a user context. A user adding a custom defined component.
pub fn add_vanity<C: VanityControlData>(
&mut self,
vanity_control: VanityControlBuilder<FD, FS, C>,
vanity_control: VanityControlBuilder<FD, C>,
) {
let BuiltVanityControlData {
render_data,
getter,
} = 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 view = VanityControlData::build_control(fs, render_data, value_getter);
(view, None)
@ -92,7 +106,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
// TODO: test this from a user context. A user adding a custom defined component.
pub fn add_control<C: ControlData, FDT: Clone + PartialEq + 'static>(
&mut self,
control: ControlBuilder<FD, FS, C, FDT>,
control: ControlBuilder<FD, C, FDT>,
) {
let built_control_data = match control.build() {
Ok(c) => c,
@ -103,7 +117,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
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);
(view, Some(cb))
};
@ -113,8 +127,8 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
fn build_control_view<C: ControlData, FDT: 'static>(
fd: RwSignal<FD>,
fs: &FS,
control_data: BuiltControlData<FD, FS, C, FDT>,
fs: &FD::Style,
control_data: BuiltControlData<FD, C, FDT>,
) -> (View, Box<dyn ValidationCb>) {
let BuiltControlData {
render_data,
@ -211,7 +225,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
self,
action: Action<ServFn, Result<ServFn::Output, ServerFnError<ServFn::Error>>>,
fd: FD,
fs: FS,
fs: FD::Style,
) -> Form<FD>
where
ServFn: DeserializeOwned + ServerFn<InputEncoding = PostUrl> + 'static,
@ -256,7 +270,7 @@ impl<FD: FormToolData, FS: FormStyle, CX: 'static> FormBuilder<FD, FS, CX> {
}
}
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 (views, validation_cbs): (Vec<_>, Vec<_>) = self

View File

@ -365,7 +365,7 @@ impl FormStyle for GridFormStyle {
let action = control.data.action.clone();
let on_click = move |ev: MouseEvent| {
if let Some(action) = action.clone() {
data_signal.update(|fd| action(ev, fd));
action(ev, data_signal)
}
};