Skip to main content

kayrx_ui/widget/input/
input_number.rs

1use web_sys::HtmlInputElement;
2use crate::fabric::prelude::*;
3
4pub struct InputNumber {
5    link: ComponentLink<Self>,
6    oninput: Callback<Option<f64>>,
7    value: String,
8    node_ref: NodeRef,
9    disabled: bool,
10}
11pub enum Msg {
12    Input(String),
13}
14
15#[derive(Clone, Properties)]
16pub struct Props {
17    #[prop_or_else(Callback::noop)]
18    pub oninput: Callback<Option<f64>>,
19    #[prop_or_default]
20    pub value: Option<f64>,
21    #[prop_or_default]
22    pub disabled: bool,
23}
24impl Component for InputNumber {
25    type Message = Msg;
26    type Properties = Props;
27
28    fn create(props: Self::Properties, link: ComponentLink<Self>) -> Self {
29        InputNumber {
30            link,
31            oninput: props.oninput,
32            value: props.value.map_or("".into(), |v| v.to_string()),
33            disabled: props.disabled,
34            node_ref: NodeRef::default(),
35        }
36    }
37
38    fn update(&mut self, msg: Self::Message) -> ShouldRender {
39        match msg {
40            Msg::Input(v) => {
41                let old = if let Ok(fv) = self.value.parse::<f64>() {
42                    Some(fv)
43                } else {
44                    None
45                };
46                let res = if v.len() == 0 {
47                    self.value = "".into();
48                    None
49                } else if let Ok(fv) = v.parse::<f64>() {
50                    self.value = v.clone().into();
51                    Some(fv)
52                } else {
53                    old
54                };
55
56                if old != res {
57                    self.oninput.emit(res);
58                }
59                if self.value != v {
60                    if let Some(el) = self.node_ref.cast::<HtmlInputElement>() {
61                        if el.value() != self.value {
62                            el.set_value(&self.value);
63                        }
64                    }
65                }
66            }
67        }
68        false
69    }
70
71    fn change(&mut self, props: Self::Properties) -> ShouldRender {
72        self.value = props.value.map_or("".into(), |v| v.to_string());
73        self.oninput = props.oninput;
74        true
75    }
76
77    fn view(&self) -> Html {
78        html! {
79            <div class="bow-input-number">
80                <input ref=self.node_ref.clone()
81                    value=&self.value
82                    disabled=self.disabled
83                    oninput=self.link.callback(|v: InputData| Msg::Input(v.value))>
84                </input>
85            </div>
86        }
87    }
88}