From d6730d0e23deed70a5f6d411c9bf58e8a72ca334 Mon Sep 17 00:00:00 2001 From: luoxiao <luoxiaozero@163.com> Date: Wed, 8 Nov 2023 21:53:49 +0800 Subject: [PATCH] feat: auto complete component add clear after select --- demo/src/components/site_header.rs | 12 +++++++++++- demo/src/pages/components.rs | 23 ++++++++++++----------- src/auto_complete/mod.rs | 18 ++++++++++++++++-- 3 files changed, 39 insertions(+), 14 deletions(-) diff --git a/demo/src/components/site_header.rs b/demo/src/components/site_header.rs index e9f6a4b..abef5ba 100644 --- a/demo/src/components/site_header.rs +++ b/demo/src/components/site_header.rs @@ -69,6 +69,10 @@ pub fn SiteHeader() -> impl IntoView { .collect() }) }); + let on_search_select = move |path: String| { + let navigate = use_navigate(); + navigate(&path, Default::default()); + }; view! { <LayoutHeader style> <Space> @@ -85,7 +89,13 @@ pub fn SiteHeader() -> impl IntoView { </div> </Space> <Space> - <AutoComplete value=search_value placeholder="Search" options=search_options/> + <AutoComplete + value=search_value + placeholder="Search" + options=search_options + clear_after_select=true + on_select=on_search_select + /> <Button variant=ButtonVariant::Text on:click=move |_| { diff --git a/demo/src/pages/components.rs b/demo/src/pages/components.rs index 2f7063c..50e0b63 100644 --- a/demo/src/pages/components.rs +++ b/demo/src/pages/components.rs @@ -6,30 +6,31 @@ use thaw::*; #[component] pub fn ComponentsPage() -> impl IntoView { let navigate = use_navigate(); - let selected = create_rw_signal({ - let loaction = use_location(); - let mut pathname = loaction.pathname.get_untracked(); + let loaction = use_location(); - if pathname.starts_with("/thaw/components/") { + let select_name = create_rw_signal(String::new()); + create_effect(move |_| { + let mut pathname = loaction.pathname.get(); + let name = if pathname.starts_with("/thaw/components/") { pathname.drain(17..).collect() } else { String::new() - } + }; + select_name.set(name); }); - create_effect(move |value| { - let selected = selected.get(); - if value.is_some() { - navigate(&format!("/components/{selected}"), Default::default()); + _ = select_name.watch(move |name| { + let pathname = loaction.pathname.get_untracked(); + if !pathname.starts_with(&format!("/thaw/components/{name}")) { + navigate(&format!("/components/{name}"), Default::default()); } - selected }); view! { <Layout position=LayoutPosition::Absolute> <SiteHeader/> <Layout has_sider=true position=LayoutPosition::Absolute style="top: 64px;"> <LayoutSider> - <Menu value=selected> + <Menu value=select_name> { gen_menu_data().into_view() } diff --git a/src/auto_complete/mod.rs b/src/auto_complete/mod.rs index 23a4b5d..2f34d12 100644 --- a/src/auto_complete/mod.rs +++ b/src/auto_complete/mod.rs @@ -1,7 +1,11 @@ mod theme; use crate::{ - mount_style, teleport::Teleport, use_theme, utils::maybe_rw_signal::MaybeRwSignal, Input, Theme, + mount_style, + teleport::Teleport, + use_theme, + utils::{maybe_rw_signal::MaybeRwSignal, StoredMaybeSignal}, + Input, Theme, }; use leptos::*; pub use theme::AutoCompleteTheme; @@ -17,6 +21,8 @@ pub fn AutoComplete( #[prop(optional, into)] value: MaybeRwSignal<String>, #[prop(optional, into)] placeholder: MaybeSignal<String>, #[prop(optional, into)] options: MaybeSignal<Vec<AutoCompleteOption>>, + #[prop(optional, into)] clear_after_select: MaybeSignal<bool>, + #[prop(optional, into)] on_select: Option<Callback<String>>, ) -> impl IntoView { mount_style("auto-complete", include_str!("./auto-complete.css")); let theme = use_theme(Theme::light); @@ -38,6 +44,7 @@ pub fn AutoComplete( let is_show_menu = create_rw_signal(false); let auto_complete_ref = create_node_ref::<html::Div>(); let auto_complete_menu_ref = create_node_ref::<html::Div>(); + let options = StoredMaybeSignal::from(options); let show_menu = move || { is_show_menu.set(true); let rect = auto_complete_ref @@ -96,7 +103,14 @@ pub fn AutoComplete( .map(|v| { let AutoCompleteOption { value: option_value, label } = v; let on_click = move |_| { - value.set(option_value.clone()); + if clear_after_select.get_untracked() { + value.set(String::new()); + } else { + value.set(option_value.clone()); + } + if let Some(on_select) = on_select { + on_select.call(option_value.clone()); + } is_show_menu.set(false); }; let on_mousedown = move |ev: ev::MouseEvent| {