From 4c6b6fa920fba6449bf1e4ac940fcb5eab1839fd Mon Sep 17 00:00:00 2001 From: Mitchell M Date: Wed, 12 Jun 2024 17:25:05 -0500 Subject: [PATCH] add context --- src/controls/button.rs | 2 +- src/controls/checkbox.rs | 2 +- src/controls/custom.rs | 2 +- src/controls/group.rs | 12 +++++++++--- src/controls/heading.rs | 2 +- src/controls/hidden.rs | 2 +- src/controls/output.rs | 2 +- src/controls/radio_buttons.rs | 2 +- src/controls/select.rs | 2 +- src/controls/slider.rs | 2 +- src/controls/spacer.rs | 2 +- src/controls/stepper.rs | 2 +- src/controls/submit.rs | 2 +- src/controls/text_area.rs | 2 +- src/controls/text_input.rs | 2 +- src/form.rs | 36 ++++++++++++++++++++++------------- src/form_builder.rs | 13 ++++++++++--- 17 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/controls/button.rs b/src/controls/button.rs index a3d39fe..a8cbf7d 100644 --- a/src/controls/button.rs +++ b/src/controls/button.rs @@ -20,7 +20,7 @@ impl Default for ButtonData { } } -impl FormBuilder { +impl FormBuilder { pub fn button( mut self, builder: impl Fn(ButtonBuilder) -> ButtonBuilder, diff --git a/src/controls/checkbox.rs b/src/controls/checkbox.rs index 67bd179..5955a4d 100644 --- a/src/controls/checkbox.rs +++ b/src/controls/checkbox.rs @@ -23,7 +23,7 @@ impl ControlData for CheckboxData { } } -impl FormBuilder { +impl FormBuilder { pub fn checkbox( self, builder: impl Fn( diff --git a/src/controls/custom.rs b/src/controls/custom.rs index fc867b9..48dd601 100644 --- a/src/controls/custom.rs +++ b/src/controls/custom.rs @@ -1,7 +1,7 @@ use super::{ControlBuilder, ControlData}; use crate::{styles::FormStyle, FormBuilder, FormToolData}; -impl FormBuilder { +impl FormBuilder { pub fn custom( mut self, control_data: CC, diff --git a/src/controls/group.rs b/src/controls/group.rs index 27711ac..8edfbd6 100644 --- a/src/controls/group.rs +++ b/src/controls/group.rs @@ -2,11 +2,17 @@ use super::ValidationCb; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; use leptos::{CollectView, RwSignal}; -impl FormBuilder { - pub fn group(mut self, builder: impl Fn(FormBuilder) -> FormBuilder) -> Self { - let mut group_builder = FormBuilder::new(); +impl FormBuilder { + pub fn group( + mut self, + builder: impl Fn(FormBuilder) -> FormBuilder, + ) -> Self { + let mut group_builder = FormBuilder::new(self.cx); group_builder = builder(group_builder); + // Take context back + self.cx = group_builder.cx; + for validation in group_builder.validations { self.validations.push(validation); } diff --git a/src/controls/heading.rs b/src/controls/heading.rs index 1f95191..4a40770 100644 --- a/src/controls/heading.rs +++ b/src/controls/heading.rs @@ -17,7 +17,7 @@ impl VanityControlData for HeadingData { } } -impl FormBuilder { +impl FormBuilder { pub fn heading( self, builder: impl Fn( diff --git a/src/controls/hidden.rs b/src/controls/hidden.rs index 88bcafc..e5da92c 100644 --- a/src/controls/hidden.rs +++ b/src/controls/hidden.rs @@ -20,7 +20,7 @@ impl ControlData for HiddenData { } } -impl FormBuilder { +impl FormBuilder { pub fn hidden( self, builder: impl Fn( diff --git a/src/controls/output.rs b/src/controls/output.rs index d13500c..c68e779 100644 --- a/src/controls/output.rs +++ b/src/controls/output.rs @@ -17,7 +17,7 @@ impl VanityControlData for OutputData { } impl GetterVanityControlData for OutputData {} -impl FormBuilder { +impl FormBuilder { pub fn output( self, builder: impl Fn( diff --git a/src/controls/radio_buttons.rs b/src/controls/radio_buttons.rs index 6fa8961..7866b8d 100644 --- a/src/controls/radio_buttons.rs +++ b/src/controls/radio_buttons.rs @@ -25,7 +25,7 @@ impl ControlData for RadioButtonsData { } impl ValidatedControlData for RadioButtonsData {} -impl FormBuilder { +impl FormBuilder { pub fn radio_buttons( self, builder: impl Fn( diff --git a/src/controls/select.rs b/src/controls/select.rs index e86d268..5b63aea 100644 --- a/src/controls/select.rs +++ b/src/controls/select.rs @@ -27,7 +27,7 @@ impl ControlData for SelectData { } impl ValidatedControlData for SelectData {} -impl FormBuilder { +impl FormBuilder { pub fn select( self, builder: impl Fn( diff --git a/src/controls/slider.rs b/src/controls/slider.rs index 3cd5b5b..e333777 100644 --- a/src/controls/slider.rs +++ b/src/controls/slider.rs @@ -38,7 +38,7 @@ impl ControlData for SliderData { } } -impl FormBuilder { +impl FormBuilder { pub fn slider( self, builder: impl Fn( diff --git a/src/controls/spacer.rs b/src/controls/spacer.rs index e65e864..0b665f5 100644 --- a/src/controls/spacer.rs +++ b/src/controls/spacer.rs @@ -18,7 +18,7 @@ impl VanityControlData for SpacerData { } } -impl FormBuilder { +impl FormBuilder { pub fn spacer( self, builder: impl Fn( diff --git a/src/controls/stepper.rs b/src/controls/stepper.rs index f874d6f..008b12c 100644 --- a/src/controls/stepper.rs +++ b/src/controls/stepper.rs @@ -29,7 +29,7 @@ impl ControlData for StepperData { } impl ValidatedControlData for StepperData {} -impl FormBuilder { +impl FormBuilder { pub fn stepper( self, builder: impl Fn( diff --git a/src/controls/submit.rs b/src/controls/submit.rs index 487799e..d6f706e 100644 --- a/src/controls/submit.rs +++ b/src/controls/submit.rs @@ -18,7 +18,7 @@ impl VanityControlData for SubmitData { } } -impl FormBuilder { +impl FormBuilder { pub fn submit( self, builder: impl Fn( diff --git a/src/controls/text_area.rs b/src/controls/text_area.rs index ea1214f..804f3dc 100644 --- a/src/controls/text_area.rs +++ b/src/controls/text_area.rs @@ -23,7 +23,7 @@ impl ControlData for TextAreaData { } impl ValidatedControlData for TextAreaData {} -impl FormBuilder { +impl FormBuilder { pub fn text_area( self, builder: impl Fn( diff --git a/src/controls/text_input.rs b/src/controls/text_input.rs index dd62869..61fb3d9 100644 --- a/src/controls/text_input.rs +++ b/src/controls/text_input.rs @@ -39,7 +39,7 @@ impl ControlData for TextInputData { } impl ValidatedControlData for TextInputData {} -impl FormBuilder { +impl FormBuilder { pub fn text_input( self, builder: impl Fn( diff --git a/src/form.rs b/src/form.rs index 3d62d03..ec49e59 100644 --- a/src/form.rs +++ b/src/form.rs @@ -40,15 +40,16 @@ pub struct Form { impl Form { /// Gets the [`Validator`] for this form. - pub fn validator(self) -> FormValidator { + pub fn validator(&self) -> FormValidator { FormValidator { - validations: self.validations, + validations: self.validations.clone(), } } /// Validates the [`ToolFormData`], returning the result 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`]. @@ -80,6 +81,7 @@ impl IntoView for Form { /// to physically lay out a form, and how that data should be parsed and validated. pub trait FormToolData: Clone + 'static { type Style: FormStyle; + type Context: 'static; /// Defines how the form should be layed out and how the data should be parsed and validated. /// @@ -88,7 +90,9 @@ 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) -> FormBuilder; + fn build_form( + fb: FormBuilder, + ) -> FormBuilder; /// Constructs a [`Form`] for this [`FormToolData`] type. /// @@ -96,8 +100,13 @@ pub trait FormToolData: Clone + 'static { /// [`Form`](leptos_router::Form) /// component. Call [`get_action_form`]\() to get the /// [`ActionForm`](leptos_router::ActionForm) version. - fn get_form(self, action: impl ToString, style: Self::Style) -> Form { - let builder = FormBuilder::new(); + fn get_form( + self, + action: impl ToString, + style: Self::Style, + context: Self::Context, + ) -> Form { + let builder = FormBuilder::new(context); let builder = Self::build_form(builder); builder.build_plain_form(action.to_string(), self, style) } @@ -112,13 +121,14 @@ pub trait FormToolData: Clone + 'static { self, action: Action>>, style: Self::Style, + context: Self::Context, ) -> Form where ServFn: DeserializeOwned + ServerFn + 'static, <>::Request as ClientReq>::FormData: From, { - let builder = FormBuilder::new(); + let builder = FormBuilder::new(context); let builder = Self::build_form(builder); builder.build_action_form(action, self, style) } @@ -131,18 +141,18 @@ pub trait FormToolData: 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 { - let builder = FormBuilder::new(); + fn get_validator(context: Self::Context) -> FormValidator { + let builder = FormBuilder::new(context); let builder = Self::build_form(builder); builder.validator() } /// Validates this [`FormToolData`] struct. /// - /// This is shorthand for creating a validator with [`get_validator`]\() - /// and then calling `validator.validate(&self)`. - fn validate(&self) -> Result<(), String> { - let validator = Self::get_validator(); + /// This is shorthand for creating a validator with [`get_validator`] + /// and then calling `validator.validate(&self, context)`. + fn validate(&self, context: Self::Context) -> Result<(), String> { + let validator = Self::get_validator(context); validator.validate(self) } } diff --git a/src/form_builder.rs b/src/form_builder.rs index de96f90..81e57d1 100644 --- a/src/form_builder.rs +++ b/src/form_builder.rs @@ -19,7 +19,13 @@ use web_sys::{FormData, SubmitEvent}; /// A builder for laying out forms. /// /// This builder allows you to specify what components should make up the form. -pub struct FormBuilder { +/// +/// ### 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 { + pub(crate) cx: CX, /// The list of [`ValidationFn`]s. pub(crate) validations: Vec>>, /// The list of functions that will render the form. @@ -28,10 +34,11 @@ pub struct FormBuilder { pub(crate) styles: Vec, } -impl FormBuilder { +impl FormBuilder { /// Creates a new [`FormBuilder`] - pub(crate) fn new() -> FormBuilder { + pub(crate) fn new(cx: CX) -> Self { FormBuilder { + cx, validations: Vec::new(), render_fns: Vec::new(), styles: Vec::new(),