yew_utils/components/
drop_down_plain.rs

1use std::fmt::Display;
2use web_sys::HtmlSelectElement;
3use yew::prelude::*;
4
5pub struct DropDown<T> {
6    selected: T,
7    node: NodeRef,
8}
9
10pub enum Msg {
11    SelectionChanged(usize),
12}
13
14#[derive(PartialEq, Properties)]
15pub struct DropDownProps<T>
16where
17    T: PartialEq,
18{
19    pub initial: T,
20    pub options: Vec<T>,
21    pub selection_changed: Callback<T>,
22}
23
24impl<T> Component for DropDown<T>
25where
26    T: Display + Clone + PartialEq + 'static,
27{
28    type Message = Msg;
29    type Properties = DropDownProps<T>;
30
31    fn create(ctx: &Context<Self>) -> Self {
32        Self {
33            selected: ctx.props().initial.clone(),
34            node: NodeRef::default(),
35        }
36    }
37
38    fn view(&self, ctx: &Context<Self>) -> Html {
39        let node = self.node.clone();
40
41        html! {
42            <select ref={node.clone()} onchange={ctx.link().callback(move |_| {
43                let node2: HtmlSelectElement = node.cast().unwrap();
44                let idx = node2.selected_index() as usize;
45                Msg::SelectionChanged(idx)
46            })}>
47            {
48                for ctx.props().options.iter().map(|opt| {
49                    if opt == &self.selected {
50                        html! {
51                            <option value={opt.to_string()} selected=true>{opt}</option>
52                        }
53                    } else {
54                        html! {
55                            <option value={opt.to_string()}>{opt}</option>
56                        }
57                    }
58                })
59
60            }
61            </select>
62        }
63    }
64
65    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
66        match msg {
67            Msg::SelectionChanged(idx) => {
68                if let Some(selected) = ctx.props().options.get(idx) {
69                    self.selected = selected.clone();
70                    ctx.props().selection_changed.emit(selected.clone());
71                }
72                true
73            }
74        }
75    }
76}