use crate::common::ValueType; use leptos::ev::{Event, Targeted}; use leptos::prelude::*; use leptos::web_sys::HtmlSelectElement; use std::collections::HashMap; use leptos::logging::{log, warn}; use crate::components::{use_validation_context, InputState, ValidationState}; fn validate(required: bool, value: String) -> ValidationState { if required && (value.is_empty()) { ValidationState::Invalid("This input is required.".to_string()) } else { ValidationState::Valid } } /// A custom-styled select input. /// /// Takes a `Vec` as the set of inputs. Only one value may be selected, which is indicated /// by the `value` prop of the component. #[component] pub fn Select( #[prop()] value_list: Vec, #[prop(optional)] value: RwSignal, #[prop(into)] data_member: Signal, #[prop()] data_map: RwSignal>, #[prop(optional, into)] label: String, #[prop(optional, into)] disabled: Signal, #[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()))); }); }); //#endregion //#region Validation Logic let error = RwSignal::new( validate(required.get_untracked(), raw_value.get_untracked()) ); warn!("Current error state: {:?}", error.get_untracked()); let dirty = RwSignal::new(false); let show_errors = Signal::derive(move || dirty.get() && matches!(error.get(), ValidationState::Invalid(_))); let input_state = InputState::new(data_member.get(), error.clone(), dirty.clone()); let validation_context = use_validation_context() .expect("Could not find FormValidationRegistry context"); validation_context.validators.update(|list| list.push(RwSignal::new(input_state))); //#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))); } }); }; //#endregion view! {
{move || { match error.get() { ValidationState::Invalid(msg) => msg, _ => "There is no error - should not see this message.".to_string() } }}
} }