patternfly_yew/components/select/
mod.rs

1//! Select control
2
3use crate::prelude::*;
4use yew::prelude::*;
5
6/// Properties for [`SimpleSelect`].
7#[derive(PartialEq, Properties)]
8pub struct SimpleSelectProperties<T>
9where
10    T: Clone + Eq + SelectItemRenderer,
11{
12    #[prop_or_default]
13    pub placeholder: Option<String>,
14
15    #[prop_or_default]
16    pub entries: Vec<T>,
17
18    #[prop_or_default]
19    pub selected: Option<T>,
20
21    #[prop_or_default]
22    pub onselect: Callback<T>,
23}
24
25/// Render an item for the [`SimpleSelect`] component.
26pub trait SelectItemRenderer {
27    type Item;
28
29    fn label(&self) -> String;
30}
31
32impl<T> SelectItemRenderer for T
33where
34    T: std::fmt::Display,
35{
36    type Item = T;
37
38    fn label(&self) -> String {
39        self.to_string()
40    }
41}
42
43/// A simple select component.
44///
45/// > A *select* list enables users to select one or more items from a list. Use a select list when options are dynamic or variable.
46///
47/// See: <https://www.patternfly.org/components/menus/select>
48///
49#[function_component(SimpleSelect)]
50pub fn simple_select<T>(props: &SimpleSelectProperties<T>) -> Html
51where
52    T: Clone + Eq + SelectItemRenderer + 'static,
53{
54    let text = props
55        .selected
56        .as_ref()
57        .map(|s| s.label())
58        .or_else(|| props.placeholder.clone());
59
60    html!(
61        <Dropdown
62            text={text.clone()}
63        >
64            { for props.entries.iter().map(|entry| {
65                html_nested!(
66                    <Raw>
67                        <SimpleSelectItem<T>
68                            entry={entry.clone()}
69                            selected={props.selected.as_ref() == Some(entry)}
70                            onselect={props.onselect.clone()}
71                        />
72                    </Raw>
73                )
74            }) }
75        </Dropdown>
76    )
77}
78
79#[derive(PartialEq, Properties)]
80struct SimpleSelectItemProperties<T>
81where
82    T: Eq + SelectItemRenderer + 'static,
83{
84    entry: T,
85    selected: bool,
86    onselect: Callback<T>,
87}
88
89/// An item of the [`SimpleSelect`] component.
90#[function_component(SimpleSelectItem)]
91fn simple_select_item<T>(props: &SimpleSelectItemProperties<T>) -> Html
92where
93    T: Clone + Eq + SelectItemRenderer + 'static,
94{
95    let onclick = use_callback(
96        (props.entry.clone(), props.onselect.clone()),
97        |_, (entry, onselect)| {
98            log::info!("Emit: {}", entry.label());
99            onselect.emit(entry.clone());
100        },
101    );
102
103    html!(
104        <MenuAction
105            {onclick}
106            selected={props.selected}
107        >
108            { props.entry.label() }
109        </MenuAction>)
110}