Skip to main content

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(value: Value<bool>, params: SwitchParams, i: AttrGroup) {
51    let toggle = bind!(value, |_| transaction(|ctx| value.set(!value.get(ctx))));
52
53    match params.display_type {
54        DisplayType::Button => {
55            let symbol = value.map(move |value| {
56                if value {
57                    params.on_symbol.clone()
58                } else {
59                    params.off_symbol.clone()
60                }
61            });
62
63            dom! {
64                <button on_click={toggle} {..i}>{symbol}</button>
65            }
66        }
67        DisplayType::CheckBox => {
68            let value_clone = value.clone();
69            value.render_value(move |value_inner| {
70                let toggle = bind!(value_clone, |_| transaction(
71                    |ctx| value_clone.set(!value_clone.get(ctx))
72                ));
73                let i = i.clone();
74                if value_inner {
75                    dom! {
76                        <input type="checkbox" on_click={toggle} checked="checked" {..i} />
77                    }
78                } else {
79                    dom! {
80                        <input type="checkbox" on_click={toggle} {..i} />
81                    }
82                }
83            })
84
85            // Following doesn't work as browsers reads attribute 'checked' only on first render
86            // let checked = value.map(move |value|
87            //     if value { Some("checked".to_string()) } else { None }
88            // );
89            // dom! {
90            //     <input type="checkbox" on_click={toggle} checked={checked} />
91            // }
92        }
93    }
94}