diff --git a/src/controls/group.rs b/src/controls/group.rs index 8baa308..c4db082 100644 --- a/src/controls/group.rs +++ b/src/controls/group.rs @@ -1,6 +1,6 @@ use super::{ControlRenderData, VanityControlBuilder, VanityControlData}; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; -use leptos::View; +use leptos::{Signal, View}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct GroupData { @@ -8,7 +8,11 @@ pub struct GroupData { } impl VanityControlData for GroupData { - fn build_control(fs: &FS, control: ControlRenderData) -> View { + fn build_control( + fs: &FS, + control: ControlRenderData, + _value_getter: Option>, + ) -> View { fs.group(control) } } @@ -16,13 +20,15 @@ impl VanityControlData for GroupData { impl FormBuilder { pub fn group( self, - builder: impl Fn(VanityControlBuilder) -> VanityControlBuilder, + builder: impl Fn( + VanityControlBuilder, + ) -> VanityControlBuilder, ) -> Self { self.new_vanity(builder) } } -impl VanityControlBuilder { +impl VanityControlBuilder { pub fn title(mut self, title: impl ToString) -> Self { self.data.title = Some(title.to_string()); self diff --git a/src/controls/heading.rs b/src/controls/heading.rs index 0a66103..c9d05a9 100644 --- a/src/controls/heading.rs +++ b/src/controls/heading.rs @@ -8,21 +8,28 @@ pub struct HeadingData { } impl VanityControlData for HeadingData { - fn build_control(fs: &FS, control: ControlRenderData) -> View { + fn build_control( + fs: &FS, + control: ControlRenderData, + _value_getter: Option>, + ) -> View { fs.heading(control) } } +// TODO: impl GetterVanityControl impl FormBuilder { pub fn heading( self, - builder: impl Fn(VanityControlBuilder) -> VanityControlBuilder, + builder: impl Fn( + VanityControlBuilder, + ) -> VanityControlBuilder, ) -> Self { self.new_vanity(builder) } } -impl VanityControlBuilder { +impl VanityControlBuilder { pub fn title(mut self, title: impl ToString) -> Self { self.data.title = title.to_string(); self diff --git a/src/controls/mod.rs b/src/controls/mod.rs index fc114ea..65dedae 100644 --- a/src/controls/mod.rs +++ b/src/controls/mod.rs @@ -41,8 +41,13 @@ impl RenderFn for F where /// A trait for the data needed to render an read-only control. pub trait VanityControlData: 'static { /// Builds the control, returning the [`View`] that was built. - fn build_control(fs: &FS, control: ControlRenderData) -> View; + fn build_control( + fs: &FS, + control: ControlRenderData, + value_getter: Option>, + ) -> View; } +pub trait GetterVanityControlData: VanityControlData {} /// A trait for the data needed to render an interactive control. pub trait ControlData: 'static { @@ -66,29 +71,51 @@ pub struct ControlRenderData { } /// The data needed to render a read-only control of type `C`. -pub struct VanityControlBuilder { +pub struct VanityControlBuilder { pub(crate) style_attributes: Vec, pub(crate) data: C, + pub(crate) getter: Option>>, } -impl VanityControlBuilder { +pub(crate) struct BuiltVanityControlData { + pub(crate) render_data: ControlRenderData, + pub(crate) getter: Option>>, +} + +impl VanityControlBuilder { /// Creates a new [`VanityControlBuilder`] with the given [`VanityControlData`]. pub(crate) fn new(data: C) -> Self { VanityControlBuilder { data, style_attributes: Vec::new(), + getter: None, } } /// Builds the builder into the data needed to render the control. - pub(crate) fn build(self) -> ControlRenderData { - ControlRenderData { - data: Box::new(self.data), - style: self.style_attributes, + pub(crate) fn build(self) -> BuiltVanityControlData { + BuiltVanityControlData { + render_data: ControlRenderData { + data: Box::new(self.data), + style: self.style_attributes, + }, + getter: self.getter, } } } +impl VanityControlBuilder { + /// Sets the getter function. + /// + /// This function can get a string from the form data to be displayed + /// + /// Setting this getter field is NOT required for vanity controls like this one. + pub fn getter(mut self, getter: impl FieldGetter) -> Self { + self.getter = Some(Rc::new(getter)); + self + } +} + /// The possibilities for errors when building a control. #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] pub enum ControlBuildError { diff --git a/src/controls/output.rs b/src/controls/output.rs index f83eec6..d13500c 100644 --- a/src/controls/output.rs +++ b/src/controls/output.rs @@ -1,32 +1,29 @@ use leptos::{Signal, View}; -use super::{ControlBuilder, ControlData, ControlRenderData}; +use super::{ControlRenderData, GetterVanityControlData, VanityControlBuilder, VanityControlData}; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] pub struct OutputData; -impl ControlData for OutputData { - type ReturnType = String; - +impl VanityControlData for OutputData { fn build_control( fs: &FS, control: ControlRenderData, - value_getter: Signal, - _value_setter: Box, - _validation_state: Signal>, + value_getter: Option>, ) -> View { fs.output(control, value_getter) } } +impl GetterVanityControlData for OutputData {} impl FormBuilder { - pub fn output( + pub fn output( self, builder: impl Fn( - ControlBuilder, - ) -> ControlBuilder, + VanityControlBuilder, + ) -> VanityControlBuilder, ) -> Self { - self.new_control(builder) + self.new_vanity(builder) } } diff --git a/src/controls/submit.rs b/src/controls/submit.rs index c7cbf43..35ee7bc 100644 --- a/src/controls/submit.rs +++ b/src/controls/submit.rs @@ -9,7 +9,11 @@ pub struct SubmitData { } impl VanityControlData for SubmitData { - fn build_control(fs: &FS, control: ControlRenderData) -> View { + fn build_control( + fs: &FS, + control: ControlRenderData, + _value_getter: Option>, + ) -> View { fs.submit(control) } } @@ -17,13 +21,15 @@ impl VanityControlData for SubmitData { impl FormBuilder { pub fn submit( self, - builder: impl Fn(VanityControlBuilder) -> VanityControlBuilder, + builder: impl Fn( + VanityControlBuilder, + ) -> VanityControlBuilder, ) -> Self { self.new_vanity(builder) } } -impl VanityControlBuilder { +impl VanityControlBuilder { pub fn text(mut self, text: impl ToString) -> Self { self.data.text = text.to_string(); self diff --git a/src/form_builder.rs b/src/form_builder.rs index 71ca898..204cbd4 100644 --- a/src/form_builder.rs +++ b/src/form_builder.rs @@ -1,7 +1,8 @@ use crate::{ controls::{ - BuiltControlData, ControlBuilder, ControlData, FieldGetter, FieldSetter, ParseFn, RenderFn, - UnparseFn, ValidationCb, ValidationFn, VanityControlBuilder, VanityControlData, + BuiltControlData, BuiltVanityControlData, ControlBuilder, ControlData, FieldGetter, + FieldSetter, ParseFn, RenderFn, UnparseFn, ValidationCb, ValidationFn, + VanityControlBuilder, VanityControlData, }, form::{Form, FormToolData, Validator}, styles::FormStyle, @@ -43,7 +44,7 @@ impl FormBuilder { pub(crate) fn new_vanity( mut self, - builder: impl Fn(VanityControlBuilder) -> VanityControlBuilder, + builder: impl Fn(VanityControlBuilder) -> VanityControlBuilder, ) -> Self { let vanity_builder = VanityControlBuilder::new(C::default()); let control = builder(vanity_builder); @@ -64,12 +65,16 @@ impl FormBuilder { // TODO: test this from a user context. A user adding a custom defined component. pub fn add_vanity( &mut self, - vanity_control: VanityControlBuilder, + vanity_control: VanityControlBuilder, ) { - let render_data = vanity_control.build(); + let BuiltVanityControlData { + render_data, + getter, + } = vanity_control.build(); - let render_fn = move |fs: &FS, _| { - let view = VanityControlData::build_control(fs, render_data); + let render_fn = move |fs: &FS, fd: RwSignal| { + let value_getter = getter.map(|getter| (move || getter(fd.get())).into_signal()); + let view = VanityControlData::build_control(fs, render_data, value_getter); (view, None) }; diff --git a/src/styles/grid_form.rs b/src/styles/grid_form.rs index 08b7b94..e010949 100644 --- a/src/styles/grid_form.rs +++ b/src/styles/grid_form.rs @@ -18,13 +18,11 @@ impl FormStyle for GridFormStyle { type StylingAttributes = GridFormStylingAttributes; fn form_frame(&self, children: View) -> View { - view! {
{children}
} - .into_view() + view! {
{children}
}.into_view() } fn heading(&self, control: ControlRenderData) -> View { - view! {

{&control.data.title}

} - .into_view() + view! {

{&control.data.title}

}.into_view() } fn text_input( @@ -115,7 +113,7 @@ impl FormStyle for GridFormStyle { fn submit(&self, control: ControlRenderData) -> View { view! { } - .into_view() + .into_view() } fn text_area( @@ -153,8 +151,7 @@ impl FormStyle for GridFormStyle { _control: ControlRenderData, value_getter: Signal, ) -> View { - view! { } - .into_view() + view! { }.into_view() } fn radio_buttons( @@ -298,16 +295,16 @@ impl FormStyle for GridFormStyle { class="form_input" /> - }.into_view() + } + .into_view() } fn output( &self, _control: ControlRenderData, - value_getter: Signal, + value_getter: Option>, ) -> View { - view! {
{move || value_getter.get()}
} - .into_view() + view! {
{move || value_getter.map(|g| g.get())}
}.into_view() } fn slider( diff --git a/src/styles/mod.rs b/src/styles/mod.rs index 160fae6..dcd2ab7 100644 --- a/src/styles/mod.rs +++ b/src/styles/mod.rs @@ -70,7 +70,7 @@ pub trait FormStyle: Default + 'static { fn output( &self, control: ControlRenderData, - value_getter: Signal, + value_getter: Option>, ) -> View; fn slider( &self,