add signals where appropriate

This commit is contained in:
Mitchell Marino 2024-06-19 11:21:28 -05:00
parent c7c98f985f
commit 3c96a15680
6 changed files with 113 additions and 74 deletions

View File

@ -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<String>,
}
impl VanityControlData for HeadingData {
@ -37,7 +37,13 @@ impl<FD: FormToolData> FormBuilder<FD> {
impl<FD: FormToolData> VanityControlBuilder<FD, HeadingData> {
/// 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<String>) -> Self {
self.data.title = MaybeSignal::Dynamic(title);
self
}
}

View File

@ -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<String>,
/// 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<Vec<(String, String)>>,
/// The display text for the blank option, if there is one.
pub blank_option: Option<String>,
}
@ -70,44 +69,51 @@ impl<FD: FormToolData, FDT> ControlBuilder<FD, SelectData, FDT> {
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<Item = impl ToString>) -> 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<Item = (impl ToString, impl ToString)>,
) -> 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<Vec<String>>) -> Self {
let options = move || {
options
.get()
.into_iter()
.map(|v| (v.clone(), v))
.collect::<Vec<_>>()
};
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<Vec<(String, String)>>) -> Self {
self.data.options = MaybeSignal::Dynamic(options);
self
}

View File

@ -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<String>,
pub min: i32,
pub max: i32,
pub min: MaybeSignal<i32>,
pub max: MaybeSignal<i32>,
}
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<FD: FormToolData, FDT> ControlBuilder<FD, SliderData, FDT> {
/// 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<i32>) -> 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<i32>) -> 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<i32>) -> Self {
self.data.max = MaybeSignal::Dynamic(max);
self
}
}

View File

@ -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<String>,
pub step: Option<i32>,
pub min: Option<i32>,
pub max: Option<i32>,
pub step: Option<MaybeSignal<i32>>,
pub min: Option<MaybeSignal<i32>>,
pub max: Option<MaybeSignal<i32>>,
}
impl ControlData for StepperData {
@ -68,26 +68,37 @@ impl<FD: FormToolData, FDT> ControlBuilder<FD, StepperData, FDT> {
/// 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<i32>) -> 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<i32>) -> 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<i32>) -> 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<i32>) -> Self {
self.data.max = Some(MaybeSignal::Dynamic(max));
self
}
}

View File

@ -32,6 +32,7 @@ impl<FD: FormToolData> FormValidator<FD> {
///
/// With this, you can render the form, get the form data, or get
/// a validator for the data.
#[derive(Clone)]
pub struct Form<FD: FormToolData> {
/// The form data signal.
pub fd: RwSignal<FD>,

View File

@ -60,8 +60,7 @@ impl FormStyle for GridFormStyle {
}
fn group(&self, group: Rc<ControlRenderData<Self, View>>) -> View {
let view = view! { <div class="form_group form_grid">{&group.data}</div> }
.into_view();
let view = view! { <div class="form_group form_grid">{&group.data}</div> }.into_view();
self.custom_component(&group.styles, view)
}
@ -76,7 +75,7 @@ impl FormStyle for GridFormStyle {
fn heading(&self, control: Rc<ControlRenderData<Self, HeadingData>>) -> View {
self.custom_component(
&control.styles,
view! { <h2 class="form_heading">{&control.data.title}</h2> }.into_view(),
view! { <h2 class="form_heading">{control.data.title.clone()}</h2> }.into_view(),
)
}
@ -264,9 +263,12 @@ impl FormStyle for GridFormStyle {
value_setter: Rc<dyn Fn(<SelectData as ControlData>::ReturnType)>,
validation_state: Signal<Result<(), String>>,
) -> 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 {
</option>
}
})
.collect_view();
.collect_view()
};
let blank_option_view = control.data.blank_option.as_ref().map(|display| {
view! {
<option value="" selected=move || { value_getter.get().as_str() == "" }>
{display}
</option>
}
});
let view = view! {
<div>
@ -294,7 +305,7 @@ impl FormStyle for GridFormStyle {
value_setter(event_target_value(&ev));
}
>
{blank_option_view}
{options_view}
</select>
}