diff --git a/packages/html/src/events/form.rs b/packages/html/src/events/form.rs index d22a5219f..75cc51978 100644 --- a/packages/html/src/events/form.rs +++ b/packages/html/src/events/form.rs @@ -1,5 +1,6 @@ use crate::file_data::FileEngine; use crate::file_data::HasFileData; +use std::ops::Deref; use std::{collections::HashMap, fmt::Debug}; use dioxus_core::Event; @@ -19,6 +20,37 @@ pub enum FormValue { VecText(Vec), } +impl From for Vec { + fn from(value: FormValue) -> Self { + match value { + FormValue::Text(s) => vec![s], + FormValue::VecText(vec) => vec, + } + } +} + +impl Deref for FormValue { + type Target = [String]; + + fn deref(&self) -> &Self::Target { + self.as_slice() + } +} + +impl FormValue { + /// Convenient way to represent Value as slice + pub fn as_slice(&self) -> &[String] { + match self { + FormValue::Text(s) => std::slice::from_ref(s), + FormValue::VecText(vec) => vec.as_slice(), + } + } + /// Convert into Vec + pub fn to_vec(self) -> Vec { + self.into() + } +} + /* DOMEvent: Send + SyncTarget relatedTarget */ pub struct FormData { inner: Box, diff --git a/packages/web/src/event.rs b/packages/web/src/event.rs index 2e9632eae..e79b55fe8 100644 --- a/packages/web/src/event.rs +++ b/packages/web/src/event.rs @@ -389,7 +389,25 @@ impl HasFormData for WebFormData { } fn values(&self) -> HashMap { - let mut values = std::collections::HashMap::new(); + let mut values = HashMap::new(); + + fn insert_value(map: &mut HashMap, key: String, new_value: String) { + match map.entry(key) { + std::collections::hash_map::Entry::Occupied(mut o) => { + let first_value = match o.get_mut() { + FormValue::Text(data) => std::mem::take(data), + FormValue::VecText(vec) => { + vec.push(new_value); + return; + } + }; + let _ = o.insert(FormValue::VecText(vec![first_value, new_value])); + } + std::collections::hash_map::Entry::Vacant(v) => { + let _ = v.insert(FormValue::Text(new_value)); + } + } + } // try to fill in form values if let Some(form) = self.element.dyn_ref::() { @@ -398,20 +416,18 @@ impl HasFormData for WebFormData { 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: Vec = - item_values.iter().filter_map(|v| v.as_string()).collect(); - - values.insert(name, FormValue::VecText(item_values)); + item_values + .iter() + .filter_map(|v| v.as_string()) + .for_each(|v| insert_value(&mut values, name.clone(), v)); } else if let Ok(item_value) = array.get(1).dyn_into::() { - values.insert(name, FormValue::Text(item_value.as_string().unwrap())); + insert_value(&mut values, name, item_value.as_string().unwrap()); } } } } - } - - // try to fill in select element values - if let Some(select) = self.element.dyn_ref::() { + } else if let Some(select) = self.element.dyn_ref::() { + // try to fill in select element values let options = get_select_data(select); values.insert("options".to_string(), FormValue::VecText(options)); } @@ -536,19 +552,7 @@ export function get_form_data(form) { const formData = new FormData(form); for (let name of formData.keys()) { - const fieldType = form.elements[name].type; - console.log(fieldType); - - 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; - } + values.set(name, formData.getAll(name)); } return values;