From 58933276c927062113980f824fb0f7cbe7c09cb5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 9 Oct 2020 20:56:09 +0200 Subject: [PATCH] Improvements over HtmlSelect to allow using hashable objects (#47) --- yewprint-doc/src/html_select/example.rs | 44 ++++++++++----- yewprint/src/html_select.rs | 72 +++++++++++++++++++------ 2 files changed, 87 insertions(+), 29 deletions(-) diff --git a/yewprint-doc/src/html_select/example.rs b/yewprint-doc/src/html_select/example.rs index 5e2391b..2d4154a 100644 --- a/yewprint-doc/src/html_select/example.rs +++ b/yewprint-doc/src/html_select/example.rs @@ -3,6 +3,8 @@ use yewprint::HtmlSelect; pub struct Example { props: ExampleProps, + link: ComponentLink, + log_level: LogLevel, } #[derive(Clone, PartialEq, Properties)] @@ -14,14 +16,19 @@ pub struct ExampleProps { } impl Component for Example { - type Message = (); + type Message = LogLevel; type Properties = ExampleProps; - fn create(props: Self::Properties, _link: ComponentLink) -> Self { - Example { props } + fn create(props: Self::Properties, link: ComponentLink) -> Self { + Example { + props, + link, + log_level: LogLevel::Info, + } } - fn update(&mut self, _msg: Self::Message) -> ShouldRender { + fn update(&mut self, msg: Self::Message) -> ShouldRender { + self.log_level = msg; true } @@ -37,21 +44,34 @@ impl Component for Example { fn view(&self) -> Html { html! {
- options={vec![ - ("trace".to_string(), "TRACE".to_string()), - ("debug".to_string(), "DEBUG".to_string()), - ("info".to_string(), "INFO".to_string()), - ("warn".to_string(), "WARN".to_string()), - ("error".to_string(), "ERROR".to_string()), - ("off".to_string(), "OFF".to_string()), - ]} + (LogLevel::Trace, "TRACE".to_string()), + (LogLevel::Debug, "DEBUG".to_string()), + (LogLevel::Info, "INFO".to_string()), + (LogLevel::Warn, "WARN".to_string()), + (LogLevel::Error, "ERROR".to_string()), + (LogLevel::Off, "OFF".to_string()), + ]} minimal=self.props.minimal fill=self.props.fill disabled=self.props.disabled large=self.props.large + value=Some(self.log_level) + onchange=self.link.callback(|x| x) + title=format!("Selected: {:?}", self.log_level) />
} } } + +#[derive(Debug, Clone, Copy, Hash, PartialEq)] +pub enum LogLevel { + Trace, + Debug, + Info, + Warn, + Error, + Off, +} diff --git a/yewprint/src/html_select.rs b/yewprint/src/html_select.rs index 8aeaf90..5ffb79f 100644 --- a/yewprint/src/html_select.rs +++ b/yewprint/src/html_select.rs @@ -1,12 +1,15 @@ use crate::{ConditionalClass, Icon, IconName}; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; use yew::prelude::*; -pub struct HtmlSelect { - props: Props, +pub struct HtmlSelect { + props: Props, + link: ComponentLink, } #[derive(Clone, PartialEq, Properties)] -pub struct Props { +pub struct Props { #[prop_or_default] pub fill: ConditionalClass, #[prop_or_default] @@ -20,23 +23,32 @@ pub struct Props { #[prop_or_default] pub title: Option, #[prop_or_default] - pub onchange: Callback, + pub onchange: Callback, + pub options: Vec<(T, String)>, #[prop_or_default] - pub options: Vec<(String, String)>, - #[prop_or_default] - pub value: String, + pub value: Option, } -impl Component for HtmlSelect { - type Message = (); - type Properties = Props; +impl Component for HtmlSelect { + type Message = ChangeData; + type Properties = Props; - fn create(props: Self::Properties, _link: ComponentLink) -> Self { - HtmlSelect { props } + fn create(props: Self::Properties, link: ComponentLink) -> Self { + Self { props, link } } - fn update(&mut self, _msg: Self::Message) -> ShouldRender { - true + fn update(&mut self, msg: Self::Message) -> ShouldRender { + let i = if let ChangeData::Select(select) = msg { + select.selected_index() + } else { + unreachable!("unexpected ChangeData variant: {:?}", msg); + }; + if i >= 0 { + let i = i as usize; + let variant = self.props.options[i].0.clone(); + self.props.onchange.emit(variant); + } + false } fn change(&mut self, props: Self::Properties) -> ShouldRender { @@ -53,7 +65,25 @@ impl Component for HtmlSelect { .props .options .iter() - .map(|(value, label)| html!()) + .map(|(value, label)| { + let selected = self + .props + .value + .as_ref() + .map(|x| value == x) + .unwrap_or_default(); + let value = { + let mut hasher = DefaultHasher::new(); + value.hash(&mut hasher); + hasher.finish() + }; + + html! { + + } + }) .collect::(); html! { @@ -68,8 +98,16 @@ impl Component for HtmlSelect { >