diff --git a/demo/src/components/switch_version.rs b/demo/src/components/switch_version.rs index 3a14f54..b9f87df 100644 --- a/demo/src/components/switch_version.rs +++ b/demo/src/components/switch_version.rs @@ -31,9 +31,7 @@ pub fn SwitchVersion() -> impl IntoView { { options.into_iter().map(|option| view! { - - {option.0} - + }).collect_view() } diff --git a/demo_markdown/docs/combobox/mod.md b/demo_markdown/docs/combobox/mod.md index 1578530..8270981 100644 --- a/demo_markdown/docs/combobox/mod.md +++ b/demo_markdown/docs/combobox/mod.md @@ -1,16 +1,12 @@ # Combobox ```rust demo -let value = RwSignal::new(vec![]); +let selected_options = RwSignal::new(vec![]); view! { - - - "Cat" - - - "Dog" - + + + } ``` @@ -18,16 +14,12 @@ view! { ### Clearable ```rust demo -let value = RwSignal::new(vec![]); +let selected_options = RwSignal::new(vec![]); view! { - - - "Cat" - - - "Dog" - + + + } ``` @@ -35,16 +27,12 @@ view! { ### Multiselect ```rust demo -let value = RwSignal::new(vec![]); +let selected_options = RwSignal::new(vec![]); view! { - - - "Cat" - - - "Dog" - + + + } ``` diff --git a/thaw/src/combobox/combobox.rs b/thaw/src/combobox/combobox.rs index 75151e3..939ec78 100644 --- a/thaw/src/combobox/combobox.rs +++ b/thaw/src/combobox/combobox.rs @@ -5,7 +5,8 @@ use thaw_utils::{add_event_listener, mount_style, Model}; #[component] pub fn Combobox( - #[prop(optional, into)] value: Model>, + #[prop(optional, into)] value: Model, + #[prop(optional, into)] selected_options: Model>, #[prop(optional)] multiselect: bool, #[prop(optional)] clearable: bool, children: Children, @@ -19,7 +20,7 @@ pub fn Combobox( let clear_icon_ref = NodeRef::::new(); let is_show_clear_icon = Memo::new(move |_| { if clearable { - value.with(|value| !value.is_empty()) + selected_options.with(|options| !options.is_empty()) } else { false } @@ -28,7 +29,7 @@ pub fn Combobox( clear_icon_ref.on_load(move |clear_icon_el| { let handler = add_event_listener(clear_icon_el.into_any(), ev::click, move |e| { e.stop_propagation(); - value.set(vec![]); + selected_options.set(vec![]); }); on_cleanup(move || handler.remove()); }); @@ -66,6 +67,32 @@ pub fn Combobox( on_cleanup(move || handle.remove()); } + let on_input = move |ev| { + let input_value = event_target_value(&ev); + if !multiselect { + if selected_options.with_untracked(|options| { + if let Some(option) = options.first() { + if option != &input_value { + return true; + } + } + false + }) { + selected_options.set(vec![]); + } + } + value.set(input_value); + }; + let on_blur = move |_| { + if multiselect { + value.set(String::new()); + } else { + if selected_options.with_untracked(|options| options.is_empty()) { + value.set(String::new()); + } + } + }; + view! {
{ if clearable { @@ -129,7 +150,7 @@ pub fn Combobox( placement=FollowerPlacement::BottomStart width=FollowerWidth::MinTarget > - + >, + value: Model, + selected_options: Model>, is_show_listbox: RwSignal, pub multiselect: bool, } @@ -165,20 +187,22 @@ impl ComboboxInjection { expect_context() } - pub fn is_selected(&self, key: &String) -> bool { - self.value.with(|value| value.contains(key)) + pub fn is_selected(&self, value: &String) -> bool { + self.selected_options + .with(|options| options.contains(value)) } - pub fn on_option_select(&self, key: &String) { - self.value.update(|value| { + pub fn on_option_select(&self, value: &String, text: &String) { + self.selected_options.update(|options| { if self.multiselect { - if let Some(index) = value.iter().position(|k| k == key) { - value.remove(index); + if let Some(index) = options.iter().position(|v| v == value) { + options.remove(index); return; } - value.push(key.clone()); + options.push(value.clone()); } else { - *value = vec![key.clone()]; + *options = vec![value.clone()]; + self.value.set(text.clone()); self.is_show_listbox.set(false); } }); diff --git a/thaw/src/combobox/combobox_option.rs b/thaw/src/combobox/combobox_option.rs index e9cab83..3cc16c2 100644 --- a/thaw/src/combobox/combobox_option.rs +++ b/thaw/src/combobox/combobox_option.rs @@ -1,12 +1,24 @@ use crate::ComboboxInjection; use leptos::*; -use thaw_components::{If, Then}; +use thaw_components::{Fallback, If, OptionComp, Then}; use thaw_utils::class_list; #[component] -pub fn ComboboxOption(#[prop(into)] key: String, children: Children) -> impl IntoView { +pub fn ComboboxOption( + #[prop(optional, into)] value: Option, + #[prop(into)] text: String, + #[prop(optional)] children: Option, +) -> impl IntoView { let combobox = ComboboxInjection::use_(); - let key = StoredValue::new(key); + let value = StoredValue::new(value.unwrap_or_else(|| text.clone())); + let text = StoredValue::new(text); + let on_click = move |_| { + text.with_value(|text| { + value.with_value(|value| { + combobox.on_option_select(value, text); + }); + }); + }; view! {
impl Int aria-selected="true" class=class_list![ "thaw-combobox-option", - ("thaw-combobox-option--selected", move || key.with_value(|key| combobox.is_selected(&key))) + ("thaw-combobox-option--selected", move || value.with_value(|value| combobox.is_selected(&value))) ] - on:click=move |_| { - key.with_value(|key| combobox.on_option_select(key)); - } + on:click=on_click > { if combobox.multiselect { view! {
} }