Made number text field generic

This commit is contained in:
Franklin 2023-04-25 19:48:03 -04:00
parent 145c062734
commit 65395552e0
2 changed files with 29 additions and 16 deletions

View File

@ -2,32 +2,31 @@
use wasm_bindgen::{JsCast, UnwrapThrowExt}; use wasm_bindgen::{JsCast, UnwrapThrowExt};
use web_sys::{HtmlInputElement}; use web_sys::{HtmlInputElement};
use yew::prelude::*; use yew::prelude::*;
use std::{str::FromStr, num::ParseFloatError}; use std::{str::FromStr, fmt::{Display}};
#[derive(Properties, PartialEq, Clone)] #[derive(Properties, PartialEq, Clone)]
pub struct NumberTextFieldProps { pub struct NumberTextFieldProps<T: PartialEq + Clone + Display + Default + FromStr> {
pub label: String, pub label: String,
pub value: UseStateHandle<f64>, pub value: UseStateHandle<T>,
#[prop_or_default] #[prop_or_default]
pub required: bool, pub required: bool,
pub onchange: Option<Callback<f64>>, pub onchange: Option<Callback<T>>,
} }
#[function_component(NumberTextField)] #[function_component(NumberTextField)]
pub fn number_textfield(props: &NumberTextFieldProps) -> Html { pub fn number_textfield<T: PartialEq + Clone + Display + Default + FromStr + 'static>(props: &NumberTextFieldProps<T>) -> Html {
let on_input_changed = { let on_input_changed = {
let handle = props.value.clone(); let handle = props.value.clone();
let onchange = props.onchange.clone(); let onchange = props.onchange.clone();
Callback::from(move |e: InputEvent| { Callback::from(move |e: InputEvent| {
let value = match get_number_value_from_input_event(e) { let value = match get_number_value_from_input_event::<T>(e) {
Ok(float) => float, Ok(float) => float,
Err(error) => { Err(_) => {
log::error!("Error ocurred attempting to parse float on input type number. This only happens in firefox browsers. {error}"); log::error!("Error ocurred attempting to parse number on input type number. This only happens in firefox browsers.");
0.0 T::default()
}}; }};
match onchange.clone() { match onchange.clone() {
Some(onchange) => onchange.emit(value), Some(onchange) => onchange.emit(value.clone()),
None => {} None => {}
}; };
handle.set(value); handle.set(value);
@ -41,9 +40,12 @@ pub fn number_textfield(props: &NumberTextFieldProps) -> Html {
} }
} }
pub fn get_number_value_from_input_event(e: InputEvent) -> Result<f64, ParseFloatError> { pub fn get_number_value_from_input_event<T: FromStr>(e: InputEvent) -> Result<T, ()> {
let event: Event = e.dyn_into().unwrap_throw(); let event: Event = e.dyn_into().unwrap_throw();
let event_target = event.target().unwrap_throw(); let event_target = event.target().unwrap_throw();
let target: HtmlInputElement = event_target.dyn_into().unwrap_throw(); let target: HtmlInputElement = event_target.dyn_into().unwrap_throw();
f64::from_str(&target.value()) match T::from_str(&target.value()) {
Ok(t) => Ok(t),
Err(_) => Err(()),
}
} }

View File

@ -1,4 +1,4 @@
use jl_types::domain::unit::Unit; use jl_types::domain::{unit::Unit, unit_type::UnitType};
use uuid::Uuid; use uuid::Uuid;
use yew::prelude::*; use yew::prelude::*;
use yew_router::prelude::use_navigator; use yew_router::prelude::use_navigator;
@ -19,7 +19,18 @@ pub fn unit_fields(props: &UnitFieldsProps) -> Html {
// Fields // Fields
let price_usd = use_state(|| 0.0); let price_usd = use_state(|| 0.0);
let unit_type_handle: UseStateHandle<Option<UnitType>> = use_state(|| None);
let rooms_handle: UseStateHandle<i16> = use_state(|| 0);
let bathrooms_handle: UseStateHandle<i16> = use_state(|| 0);
let area_handle: UseStateHandle<f32> = use_state(|| 0.0);
let a = 0.0;
let b = a as i32;
html! { html! {
<NumberTextField label={String::from("Precio en USD")} required={true} value={price_usd.clone()}/> <>
<NumberTextField<f64> label={String::from("Precio en USD")} required={true} value={price_usd.clone()}/>
<NumberTextField<f32> label={String::from("Area en m^2")} required={true} value={area_handle.clone()}/>
<NumberTextField<i16> label={String::from("Cant. de habitaciones")} required={true} value={rooms_handle.clone()}/>
<NumberTextField<i16> label={String::from("Cant. de baños")} required={true} value={bathrooms_handle.clone()}/>
</>
} }
} }