Skip to main content

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 text={html!{text.clone().unwrap_or_default()}}>
62            { for props.entries.iter().map(|entry| {
63                html_nested!(
64                    <Raw>
65                        <SimpleSelectItem<T>
66                            entry={entry.clone()}
67                            selected={props.selected.as_ref() == Some(entry)}
68                            onselect={props.onselect.clone()}
69                        />
70                    </Raw>
71                )
72            }) }
73        </Dropdown>
74    )
75}
76
77#[derive(PartialEq, Properties)]
78struct SimpleSelectItemProperties<T>
79where
80    T: Eq + SelectItemRenderer + 'static,
81{
82    entry: T,
83    selected: bool,
84    onselect: Callback<T>,
85}
86
87/// An item of the [`SimpleSelect`] component.
88#[function_component(SimpleSelectItem)]
89fn simple_select_item<T>(props: &SimpleSelectItemProperties<T>) -> Html
90where
91    T: Clone + Eq + SelectItemRenderer + 'static,
92{
93    let onclick = use_callback(
94        (props.entry.clone(), props.onselect.clone()),
95        |_, (entry, onselect)| {
96            log::info!("Emit: {}", entry.label());
97            onselect.emit(entry.clone());
98        },
99    );
100
101    html!(<MenuAction {onclick} selected={props.selected}>{ props.entry.label() }</MenuAction>)
102}