vertigo_forms/
switch.rs

1use vertigo::{AttrGroup, Value, bind, component, dom, transaction};
2
3pub enum DisplayType {
4    Button,
5    CheckBox,
6}
7
8pub struct SwitchParams {
9    pub display_type: DisplayType,
10    pub on_symbol: String,
11    pub off_symbol: String,
12}
13
14impl Default for SwitchParams {
15    fn default() -> Self {
16        Self {
17            display_type: DisplayType::Button,
18            on_symbol: "ON".to_string(),
19            off_symbol: "OFF".to_string(),
20        }
21    }
22}
23
24impl SwitchParams {
25    pub fn checkbox() -> Self {
26        Self {
27            display_type: DisplayType::CheckBox,
28            on_symbol: "".to_string(),
29            off_symbol: "".to_string(),
30        }
31    }
32}
33
34/// Simple toggle control connected to `Value<bool>`.
35///
36/// Example:
37/// ```
38/// use vertigo::{Value, dom};
39/// use vertigo_forms::{Switch, SwitchParams};
40///
41/// let toggle_value = Value::new(false);
42/// dom! {
43///     <Switch
44///         value={&toggle_value}
45///         params={}
46///     />
47/// };
48/// ```
49#[component]
50pub fn Switch(
51    value: Value<bool>,
52    params: SwitchParams,
53    i: AttrGroup, // TODO: Use
54) {
55    let toggle = bind!(value, |_| transaction(|ctx| value.set(!value.get(ctx))));
56
57    match params.display_type {
58        DisplayType::Button => {
59            let symbol = value.map(move |value| {
60                if value {
61                    params.on_symbol.clone()
62                } else {
63                    params.off_symbol.clone()
64                }
65            });
66
67            dom! {
68                <button on_click={toggle} {..i}>{symbol}</button>
69            }
70        }
71        DisplayType::CheckBox => {
72            let value_clone = value.clone();
73            value.render_value(move |value_inner| {
74                let toggle = bind!(value_clone, |_| transaction(
75                    |ctx| value_clone.set(!value_clone.get(ctx))
76                ));
77                if value_inner {
78                    dom! {
79                        <input type="checkbox" on_click={toggle} checked="checked" />
80                    }
81                } else {
82                    dom! {
83                        <input type="checkbox" on_click={toggle} />
84                    }
85                }
86            })
87
88            // Following doesn't work as browsers reads attribute 'checked' only on first render
89            // let checked = value.map(move |value|
90            //     if value { Some("checked".to_string()) } else { None }
91            // );
92            // dom! {
93            //     <input type="checkbox" on_click={toggle} checked={checked} />
94            // }
95        }
96    }
97}