From c6b39c05b704e7f0151eff00c5f6f774d7883702 Mon Sep 17 00:00:00 2001 From: Bunny Bites Date: Fri, 10 Nov 2023 11:44:19 +0530 Subject: [PATCH] 1. remove value_types from FormData. 2. modify type of values to accept dynamic type. --- packages/html/src/events/form.rs | 69 +++----------------------- packages/rink/src/hooks.rs | 5 +- packages/rink/src/widgets/button.rs | 1 - packages/rink/src/widgets/slider.rs | 1 - packages/rink/src/widgets/text_like.rs | 1 - packages/web/src/dom.rs | 40 +++++++-------- 6 files changed, 26 insertions(+), 91 deletions(-) diff --git a/packages/html/src/events/form.rs b/packages/html/src/events/form.rs index e86f72167..5bdf5124d 100644 --- a/packages/html/src/events/form.rs +++ b/packages/html/src/events/form.rs @@ -1,13 +1,13 @@ use std::{any::Any, collections::HashMap, fmt::Debug}; use dioxus_core::Event; -use serde::{de::Error, Deserialize, Serialize}; +use serde::{Deserialize, Serialize}; pub type FormEvent = Event; -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)] #[serde(untagged)] // this will serialize Text(String) -> String and VecText(Vec) to Vec -enum ValueType { +pub enum ValueType { Text(String), VecText(Vec), } @@ -18,9 +18,7 @@ enum ValueType { pub struct FormData { pub value: String, - pub values: HashMap>, - - pub value_types: HashMap, + pub values: HashMap, #[cfg_attr( feature = "serialize", @@ -42,67 +40,12 @@ where } impl FormData { - // ***** function to parse the 'values' to make it ready to use******* - // e.g - self.values = { username: ["rust"], password: ["dioxus"]} - // what we need it to be: { username: "rust", password: "dioxus"} - fn get_parsed_values(&self) -> Result { - if self.values.is_empty() { - return Err(serde_json::Error::custom("Values array is empty")); - } - - let raw_values = self.values.clone(); - - let mut parsed_values: HashMap = HashMap::new(); - - for (fieldname, values) in raw_values.into_iter() { - // check if the fieldname can hold multiple values based on its types - let field_type = self - .value_types - .get(&fieldname) - .expect("Provided invalid field"); - - let is_multi_valued_input = match field_type.as_str() { - "select" | "checkbox" => true, - _ => false, - }; - - /* - case 1 - multiple values, example { driving_types: ["manual", "automatic"] } - In this case we want to return the values as it is, NO point in making - driving_types: "manual, automatic" - - case 2 - single value, example { favourite_language: ["rust"] } - In this case we would want to deserialize the value as follows - favourite_language: "rust" - */ - parsed_values.insert( - fieldname, - if is_multi_valued_input { - // handling multiple values - case 1 - ValueType::VecText(values) - } else { - // handle single value - case 2 - ValueType::Text( - values - .into_iter() - .next() - .ok_or_else(|| serde_json::Error::custom("Values array is empty"))?, - ) - }, - ); - } - - // convert HashMap to JSON string - convert_hashmap_to_json(&parsed_values) - } - pub fn parse_json(&self) -> Result where T: serde::de::DeserializeOwned, { - let parsed_json = self - .get_parsed_values() - .expect("Failed to parse values to JSON"); + let parsed_json = + convert_hashmap_to_json(&self.values.clone()).expect("Failed to parse values to JSON"); serde_json::from_str(&parsed_json) } diff --git a/packages/rink/src/hooks.rs b/packages/rink/src/hooks.rs index 47efc9e7e..f457de29f 100644 --- a/packages/rink/src/hooks.rs +++ b/packages/rink/src/hooks.rs @@ -61,9 +61,7 @@ impl EventData { pub struct FormData { pub value: String, - pub values: HashMap>, - - pub value_types: HashMap, + pub values: HashMap, pub files: Option, } @@ -73,7 +71,6 @@ impl FormData { dioxus_html::FormData { value: self.value, values: self.values, - value_types: self.value_types, files: None, } } diff --git a/packages/rink/src/widgets/button.rs b/packages/rink/src/widgets/button.rs index 41be40da5..523b2392a 100644 --- a/packages/rink/src/widgets/button.rs +++ b/packages/rink/src/widgets/button.rs @@ -93,7 +93,6 @@ impl Button { let data = FormData { value: self.value.to_string(), values: HashMap::new(), - value_types: HashMap::new(), files: None, }; ctx.send(crate::Event { diff --git a/packages/rink/src/widgets/slider.rs b/packages/rink/src/widgets/slider.rs index dd1b50a7b..7080b6c12 100644 --- a/packages/rink/src/widgets/slider.rs +++ b/packages/rink/src/widgets/slider.rs @@ -198,7 +198,6 @@ impl Slider { let data = FormData { value: self.value.to_string(), values: HashMap::new(), - value_types: HashMap::new(), files: None, }; ctx.send(Event { diff --git a/packages/rink/src/widgets/text_like.rs b/packages/rink/src/widgets/text_like.rs index c9dacb74e..6521073d0 100644 --- a/packages/rink/src/widgets/text_like.rs +++ b/packages/rink/src/widgets/text_like.rs @@ -171,7 +171,6 @@ impl TextLike { let data: FormData = FormData { value: self.text.clone(), values: HashMap::new(), - value_types: HashMap::new(), files: None, }; let ctx: UniqueView = world.borrow().expect("expected widget context"); diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 556d9ab9a..3188e0935 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -10,7 +10,7 @@ use dioxus_core::{ BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode, }; -use dioxus_html::{event_bubbles, CompositionData, FormData, MountedData}; +use dioxus_html::{event_bubbles, CompositionData, FormData, MountedData, ValueType}; use dioxus_interpreter_js::{get_node, minimal_bindings, save_template, Channel}; use futures_channel::mpsc; use js_sys::Array; @@ -365,22 +365,7 @@ fn read_input_to_data(target: Element) -> Rc { }) .expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener"); - let mut value_types = HashMap::new(); - - // to get the input_type for the corresponding input - for input_el in target.dyn_ref::().into_iter() { - for index in 0..input_el.length() { - if let Some(element) = input_el.get_with_index(index as u32) { - if let Some(input) = element.dyn_into::().ok() { - let name = input.name(); - let input_type = input.type_(); - value_types.insert(name, input_type); - } - } - } - } - - let mut values = std::collections::HashMap::new(); + let mut values = HashMap::new(); // try to fill in form values if let Some(form) = target.dyn_ref::() { @@ -389,10 +374,12 @@ fn read_input_to_data(target: Element) -> Rc { if let Ok(array) = value.dyn_into::() { if let Some(name) = array.get(0).as_string() { if let Ok(item_values) = array.get(1).dyn_into::() { - let item_values = + let item_values: Vec = item_values.iter().filter_map(|v| v.as_string()).collect(); - values.insert(name, item_values); + values.insert(name, ValueType::VecText(item_values)); + } else if let Ok(item_value) = array.get(1).dyn_into::() { + values.insert(name, ValueType::Text(item_value.as_string().unwrap())); } } } @@ -415,7 +402,6 @@ fn read_input_to_data(target: Element) -> Rc { Rc::new(FormData { value, values, - value_types, files, }) } @@ -424,10 +410,22 @@ fn read_input_to_data(target: Element) -> Rc { #[wasm_bindgen(inline_js = r#" export function get_form_data(form) { let values = new Map(); + const formData = new FormData(form); for (let name of formData.keys()) { - values.set(name, formData.getAll(name)); + const fieldType = form.elements[name].type; + + switch (fieldType) { + case "select-multiple": + values.set(name, formData.getAll(name)); + break; + + // add cases for fieldTypes that can hold multiple values here + default: + values.set(name, formData.get(name)); + break; + } } return values;