material_yew/
slider.rs

1use crate::{bool_to_option, to_option_string};
2use gloo::events::EventListener;
3use wasm_bindgen::prelude::*;
4use wasm_bindgen::JsCast;
5use web_sys::{CustomEvent, Element};
6use yew::prelude::*;
7
8#[wasm_bindgen(module = "/build/mwc-slider.js")]
9extern "C" {
10    #[derive(Debug)]
11    type Slider;
12
13    // This needs to be added to each component
14    #[wasm_bindgen(getter, static_method_of = Slider)]
15    fn _dummy_loader() -> JsValue;
16}
17
18// call the macro with the type
19loader_hack!(Slider);
20
21/// The `mwc-snackbar` component
22///
23/// [MWC Documentation](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/slider)
24pub struct MatSlider {
25    node_ref: NodeRef,
26    input_listener: Option<EventListener>,
27    change_listener: Option<EventListener>,
28}
29
30/// Props for [`MatSlider`]
31///
32/// MWC Documentation:
33///
34/// - [Properties](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/slider#propertiesattributes)
35/// - [Events](https://github.com/material-components/material-components-web-components/tree/v0.27.0/packages/slider#events)
36#[derive(Debug, Properties, PartialEq, Clone)]
37pub struct SliderProps {
38    #[prop_or(0)]
39    pub value: u32,
40    #[prop_or(0)]
41    pub min: u32,
42    #[prop_or(100)]
43    pub max: u32,
44    #[prop_or(1)]
45    pub step: u32,
46    #[prop_or(false)]
47    pub pin: bool,
48    #[prop_or(false)]
49    pub markers: bool,
50    /// Binds to input on `mwc-slider`
51    /// Type passed to callback is `CustomEvent` because `Slider` is
52    /// undocumented See: <https://github.com/material-components/material-components-web-components/issues/1848>
53    #[prop_or_default]
54    pub oninput: Callback<CustomEvent>,
55    /// Binds to change on `mwc-slider`
56    /// Type passed to callback is `CustomEvent` because `Slider` is
57    /// undocumented See: <https://github.com/material-components/material-components-web-components/issues/1848>
58    #[prop_or_default]
59    pub onchange: Callback<CustomEvent>,
60}
61
62impl Component for MatSlider {
63    type Message = ();
64    type Properties = SliderProps;
65
66    fn create(_: &Context<Self>) -> Self {
67        Slider::ensure_loaded();
68        Self {
69            node_ref: NodeRef::default(),
70            input_listener: None,
71            change_listener: None,
72        }
73    }
74
75    fn view(&self, ctx: &Context<Self>) -> Html {
76        let props = ctx.props();
77        html! {
78             <mwc-slider
79                 value={to_option_string(props.value)}
80                 min={to_option_string(props.min)}
81                 max={to_option_string(props.max)}
82                 step={to_option_string(props.step)}
83                 pin={bool_to_option(props.pin)}
84                 markers={bool_to_option(props.markers)}
85                 ref={self.node_ref.clone()}
86             ></mwc-slider>
87        }
88    }
89
90    fn rendered(&mut self, ctx: &Context<Self>, _first_render: bool) {
91        let props = ctx.props();
92        let element = self.node_ref.cast::<Element>().unwrap();
93        if self.input_listener.is_none() {
94            let oninput = props.oninput.clone();
95            self.input_listener = Some(EventListener::new(&element, "input", move |event| {
96                oninput.emit(JsValue::from(event).unchecked_into::<CustomEvent>())
97            }));
98        };
99
100        if self.change_listener.is_none() {
101            let onchange = props.onchange.clone();
102            self.change_listener = Some(EventListener::new(&element, "change", move |event| {
103                onchange.emit(JsValue::from(event).unchecked_into::<CustomEvent>())
104            }));
105        }
106    }
107}