diff --git a/src/controls/heading.rs b/src/controls/heading.rs index 3f02b39..1733fee 100644 --- a/src/controls/heading.rs +++ b/src/controls/heading.rs @@ -1,12 +1,12 @@ use super::{BuilderCxFn, BuilderFn, ControlRenderData, VanityControlBuilder, VanityControlData}; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; -use leptos::View; +use leptos::{MaybeSignal, Signal, View}; use std::rc::Rc; /// Data used for the heading control. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct HeadingData { - pub title: String, + pub title: MaybeSignal, } impl VanityControlData for HeadingData { @@ -37,7 +37,13 @@ impl FormBuilder { impl VanityControlBuilder { /// Sets the title of this heading. pub fn title(mut self, title: impl ToString) -> Self { - self.data.title = title.to_string(); + self.data.title = MaybeSignal::Static(title.to_string()); + self + } + + /// Sets the title of this heading to a signal. + pub fn title_signal(mut self, title: Signal) -> Self { + self.data.title = MaybeSignal::Dynamic(title); self } } diff --git a/src/controls/select.rs b/src/controls/select.rs index efeb4ad..935f13c 100644 --- a/src/controls/select.rs +++ b/src/controls/select.rs @@ -2,19 +2,18 @@ use super::{ BuilderCxFn, BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData, }; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; -use leptos::{Signal, View}; +use leptos::{IntoSignal, MaybeSignal, Signal, SignalGet, View}; use std::rc::Rc; /// Data used for the select control. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Debug, Clone, PartialEq, Eq, Default)] pub struct SelectData { pub name: String, pub label: Option, /// The options for the select. /// /// The first value is the string to display, the second is the value. - // TODO: maybe signal? - pub options: Vec<(String, String)>, + pub options: MaybeSignal>, /// The display text for the blank option, if there is one. pub blank_option: Option, } @@ -70,44 +69,51 @@ impl ControlBuilder { self } - /// Adds the option to the select. - pub fn with_option(mut self, option: impl ToString) -> Self { - self.data - .options - .push((option.to_string(), option.to_string())); - self - } - - /// Adds the option to the select, specifying a different - /// value than what is displayed. - pub fn with_option_valued(mut self, display: impl ToString, value: impl ToString) -> Self { - self.data - .options - .push((display.to_string(), value.to_string())); - self - } - - /// Adds all the options in the provided iterator to the select. + /// Sets the options from the provided iterator. + /// + /// This will overwrite any pervious options setting. pub fn with_options(mut self, options: impl Iterator) -> Self { - for option in options { - self.data - .options - .push((option.to_string(), option.to_string())); - } + let options = options.map(|v| (v.to_string(), v.to_string())).collect(); + self.data.options = MaybeSignal::Static(options); self } - /// Adds all the (display_string, value) pairs in the provided iterator - /// to the select. + /// Sets the options to the (display_string, value) pairs from the + /// provided iterator. + /// + /// This will overwrite any pervious options setting. pub fn with_options_valued( mut self, options: impl Iterator, ) -> Self { - for option in options { - self.data - .options - .push((option.0.to_string(), option.1.to_string())); - } + let options = options + .map(|(d, v)| (d.to_string(), v.to_string())) + .collect(); + self.data.options = MaybeSignal::Static(options); + self + } + + /// Sets the options from the provided signal. + /// + /// This will overwrite any pervious options setting. + pub fn with_options_signal(mut self, options: Signal>) -> Self { + let options = move || { + options + .get() + .into_iter() + .map(|v| (v.clone(), v)) + .collect::>() + }; + self.data.options = MaybeSignal::Dynamic(options.into_signal()); + self + } + + /// Sets the options to the (display_string, value) pairs from the + /// provided signal. + /// + /// This will overwrite any pervious options setting. + pub fn with_options_valued_signal(mut self, options: Signal>) -> Self { + self.data.options = MaybeSignal::Dynamic(options); self } diff --git a/src/controls/slider.rs b/src/controls/slider.rs index 57567f8..129be95 100644 --- a/src/controls/slider.rs +++ b/src/controls/slider.rs @@ -1,15 +1,15 @@ use super::{BuilderCxFn, BuilderFn, ControlBuilder, ControlData, ControlRenderData}; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; -use leptos::{Signal, View}; -use std::{ops::RangeInclusive, rc::Rc}; +use leptos::{MaybeSignal, Signal, View}; +use std::rc::Rc; /// Data used for the slider control. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[derive(Debug, Clone, PartialEq, Eq)] pub struct SliderData { pub name: String, pub label: Option, - pub min: i32, - pub max: i32, + pub min: MaybeSignal, + pub max: MaybeSignal, } impl Default for SliderData { @@ -17,8 +17,8 @@ impl Default for SliderData { SliderData { name: String::new(), label: None, - min: 0, - max: 1, + min: MaybeSignal::Static(0), + max: MaybeSignal::Static(1), } } } @@ -75,21 +75,25 @@ impl ControlBuilder { /// Sets the minimum value for the slider. pub fn min(mut self, min: i32) -> Self { - self.data.min = min; + self.data.min = MaybeSignal::Static(min); + self + } + + /// Sets the minimum value for the slider to a signal. + pub fn min_signal(mut self, min: Signal) -> Self { + self.data.min = MaybeSignal::Dynamic(min); self } /// Sets the maximum value for the slider. pub fn max(mut self, max: i32) -> Self { - self.data.max = max; + self.data.max = MaybeSignal::Static(max); self } - /// Sets the minimum and maximum values for the slider by providing a - /// range. - pub fn range(mut self, range: RangeInclusive) -> Self { - self.data.min = *range.start(); - self.data.max = *range.end(); + /// Sets the maximum value for the slider to a signal. + pub fn max_signal(mut self, max: Signal) -> Self { + self.data.max = MaybeSignal::Dynamic(max); self } } diff --git a/src/controls/stepper.rs b/src/controls/stepper.rs index 8caf1d1..a8c91d2 100644 --- a/src/controls/stepper.rs +++ b/src/controls/stepper.rs @@ -2,17 +2,17 @@ use super::{ BuilderCxFn, BuilderFn, ControlBuilder, ControlData, ControlRenderData, ValidatedControlData, }; use crate::{form::FormToolData, form_builder::FormBuilder, styles::FormStyle}; -use leptos::{Signal, View}; -use std::{ops::RangeInclusive, rc::Rc}; +use leptos::{MaybeSignal, Signal, View}; +use std::rc::Rc; /// Data used for the stepper control. -#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default)] +#[derive(Debug, Default, Clone, PartialEq, Eq)] pub struct StepperData { pub name: String, pub label: Option, - pub step: Option, - pub min: Option, - pub max: Option, + pub step: Option>, + pub min: Option>, + pub max: Option>, } impl ControlData for StepperData { @@ -68,26 +68,37 @@ impl ControlBuilder { /// Sets the step ammount. pub fn step(mut self, step: i32) -> Self { - self.data.step = Some(step); + self.data.step = Some(MaybeSignal::Static(step)); self } - /// Sets a minimum value. + /// Sets the step ammount. + pub fn step_signal(mut self, step: Signal) -> Self { + self.data.step = Some(MaybeSignal::Dynamic(step)); + self + } + + /// Sets the minimum value for the slider. pub fn min(mut self, min: i32) -> Self { - self.data.min = Some(min); + self.data.min = Some(MaybeSignal::Static(min)); self } - /// Sets a maximum value. + /// Sets the minimum value for the slider to a signal. + pub fn min_signal(mut self, min: Signal) -> Self { + self.data.min = Some(MaybeSignal::Dynamic(min)); + self + } + + /// Sets the maximum value for the slider. pub fn max(mut self, max: i32) -> Self { - self.data.max = Some(max); + self.data.max = Some(MaybeSignal::Static(max)); self } - /// Sets the minimum and maximum values using the range. - pub fn range(mut self, range: RangeInclusive) -> Self { - self.data.min = Some(*range.start()); - self.data.max = Some(*range.end()); + /// Sets the maximum value for the slider to a signal. + pub fn max_signal(mut self, max: Signal) -> Self { + self.data.max = Some(MaybeSignal::Dynamic(max)); self } } diff --git a/src/form.rs b/src/form.rs index 4e5ad0b..b6a8955 100644 --- a/src/form.rs +++ b/src/form.rs @@ -32,6 +32,7 @@ impl FormValidator { /// /// With this, you can render the form, get the form data, or get /// a validator for the data. +#[derive(Clone)] pub struct Form { /// The form data signal. pub fd: RwSignal, diff --git a/src/styles/grid_form.rs b/src/styles/grid_form.rs index d519764..e954cce 100644 --- a/src/styles/grid_form.rs +++ b/src/styles/grid_form.rs @@ -60,8 +60,7 @@ impl FormStyle for GridFormStyle { } fn group(&self, group: Rc>) -> View { - let view = view! {
{&group.data}
} - .into_view(); + let view = view! {
{&group.data}
}.into_view(); self.custom_component(&group.styles, view) } @@ -76,7 +75,7 @@ impl FormStyle for GridFormStyle { fn heading(&self, control: Rc>) -> View { self.custom_component( &control.styles, - view! {

{&control.data.title}

}.into_view(), + view! {

{control.data.title.clone()}

}.into_view(), ) } @@ -132,7 +131,7 @@ impl FormStyle for GridFormStyle { style="visibility: hidden; column-span: none" /> } - .into_view() + .into_view() } fn text_input( @@ -264,9 +263,12 @@ impl FormStyle for GridFormStyle { value_setter: Rc::ReturnType)>, validation_state: Signal>, ) -> View { - let options_view = control + let control_clone = control.clone(); + let options_view = move || { + control_clone .data .options + .get() .iter() .map(|(display, value)| { let display = display.clone(); @@ -277,7 +279,16 @@ impl FormStyle for GridFormStyle { } }) - .collect_view(); + .collect_view() + }; + + let blank_option_view = control.data.blank_option.as_ref().map(|display| { + view! { + + } + }); let view = view! {
@@ -294,7 +305,7 @@ impl FormStyle for GridFormStyle { value_setter(event_target_value(&ev)); } > - + {blank_option_view} {options_view} }