From b11ad5ffff246d255a08e8c76d09fb5d7c7d5d5d Mon Sep 17 00:00:00 2001 From: Lucas Vas Date: Thu, 5 Feb 2026 00:42:55 -0500 Subject: [PATCH] feat: hydrate select component properly --- src/components/lists/single/select.rs | 98 +++++++++++++++------------ src/components/multi_entry.rs | 2 +- src/components/validated_form.rs | 1 + 3 files changed, 57 insertions(+), 44 deletions(-) diff --git a/src/components/lists/single/select.rs b/src/components/lists/single/select.rs index 9ecdf20..d77e67f 100644 --- a/src/components/lists/single/select.rs +++ b/src/components/lists/single/select.rs @@ -3,7 +3,7 @@ use leptos::ev::{Event, Targeted}; use leptos::prelude::*; use leptos::web_sys::HtmlSelectElement; use std::collections::HashMap; -use leptos::logging::{log, warn}; +use leptos::logging::log; use crate::components::{use_validation_context, InputState, ValidationState}; fn validate(required: bool, value: String) -> ValidationState { @@ -28,28 +28,29 @@ pub fn Select( #[prop(optional, into)] required: Signal ) -> impl IntoView { //#region Value Logic - - let default_raw_value = data_map.get_untracked() - .get(&data_member.get_untracked()) - .cloned() - .unwrap_or_default() - .as_string().unwrap_or_default().unwrap_or_default(); - - let raw_value = RwSignal::new(default_raw_value); - - Effect::new(move || { - data_map.update(|map| { - map.insert(data_member.get(), ValueType::String(Some(raw_value.get()))); - }); + + let value = Memo::new(move |_| { + data_map.with(|map| { + map.get(&data_member.get_untracked()) + .and_then(|v| v.as_string().ok().flatten()) + .unwrap_or_default() + }) }); + + Effect::new(move || { + log!("Current select value: {}", value.get()); + }); + + // Effect::new(move || { + // data_map.update(|map| { + // map.insert(data_member.get(), ValueType::String(Some(raw_value.get()))); + // }); + // }); //#endregion //#region Validation Logic - let error = RwSignal::new( - validate(required.get_untracked(), raw_value.get_untracked()) - ); - warn!("Current error state: {:?}", error.get_untracked()); + let error = Memo::new(move |_| validate(required.get(), value.get())); let dirty = RwSignal::new(false); let show_errors = Signal::derive(move || dirty.get() && matches!(error.get(), ValidationState::Invalid(_))); @@ -68,21 +69,29 @@ pub fn Select( //#endregion //#region Event Logic - + let on_change = move |e: Targeted| { let value = e.target().value(); - log!("Found value {}", value); - raw_value.set(value.clone()); - error.set(validate(required.get(), raw_value.get())); dirty.set(true); data_map.update(|map| { - if let Some(val) = map.get_mut(&data_member.get()) { - *val = ValueType::String(Some(value.clone())); - } else { - map.insert(data_member.get(), ValueType::String(Some(value))); - } + map.insert(data_member.get(), ValueType::String(Some(value))); }); }; + + // let on_change = move |e: Targeted| { + // let value = e.target().value(); + // log!("Found value {}", value); + // raw_value.set(value.clone()); + // error.set(validate(required.get(), raw_value.get())); + // dirty.set(true); + // data_map.update(|map| { + // if let Some(val) = map.get_mut(&data_member.get()) { + // *val = ValueType::String(Some(value.clone())); + // } else { + // map.insert(data_member.get(), ValueType::String(Some(value))); + // } + // }); + // }; //#endregion @@ -96,28 +105,31 @@ pub fn Select( transition-border duration-150 border-red-700 bg-transparent disabled:border-gray-600 disabled:pointer-events-none disabled:bg-gray-600/33" + prop:value=move || value.get() on:change:target=on_change disabled=disabled > // This closure handles the display of the options. - - {move || { - value_list - .get() - .iter() - .map(move |value| { - let display = value.to_owned(); - view! { } - }) - .collect::>() - }} + + // We can reasonably assume that the options in the list will be distinct. + {val.clone()} } + /> + // {move || { + // value_list + // .get() + // .iter() + // .map(move |value| { + // let display = value.to_owned(); + // view! { } + // }) + // .collect::>() + // }} diff --git a/src/components/multi_entry.rs b/src/components/multi_entry.rs index 4a2ffec..80d34fe 100644 --- a/src/components/multi_entry.rs +++ b/src/components/multi_entry.rs @@ -194,7 +194,7 @@ fn Entry( ) -> impl IntoView { view! {
- {schema + {move || schema .get() .iter() .map(|input_type| diff --git a/src/components/validated_form.rs b/src/components/validated_form.rs index 3e0d834..4420ccb 100644 --- a/src/components/validated_form.rs +++ b/src/components/validated_form.rs @@ -5,6 +5,7 @@ use crate::components::{ActionButton, Header}; /// Indicates the current state of an input. #[derive(Default, Debug, Clone)] +#[derive(PartialEq)] pub enum ValidationState { /// A valid input. #[default]