diff --git a/packages/html/src/events/form.rs b/packages/html/src/events/form.rs
index 361ebe2d4..6edf60448 100644
--- a/packages/html/src/events/form.rs
+++ b/packages/html/src/events/form.rs
@@ -10,7 +10,7 @@ pub type FormEvent = Event;
pub struct FormData {
pub value: String,
- pub values: HashMap,
+ pub values: HashMap>,
#[cfg_attr(feature = "serialize", serde(skip))]
pub files: Option>,
diff --git a/packages/interpreter/src/interpreter.js b/packages/interpreter/src/interpreter.js
index db453bcda..162d5c8f5 100644
--- a/packages/interpreter/src/interpreter.js
+++ b/packages/interpreter/src/interpreter.js
@@ -345,6 +345,7 @@ class Interpreter {
break;
case "NewEventListener":
let bubbles = event_bubbles(edit.name);
+
this.NewEventListener(edit.name, edit.id, bubbles, handler);
break;
}
@@ -354,7 +355,6 @@ class Interpreter {
// this handler is only provided on desktop implementations since this
// method is not used by the web implementation
function handler(event) {
- console.log(event);
let target = event.target;
if (target != null) {
let shouldPreventDefault = target.getAttribute(`dioxus-prevent-default`);
@@ -401,21 +401,14 @@ function handler(event) {
target.tagName === "FORM" &&
(event.type === "submit" || event.type === "input")
) {
- for (let x = 0; x < target.elements.length; x++) {
- let element = target.elements[x];
- let name = element.getAttribute("name");
- if (name != null) {
- if (element.getAttribute("type") === "checkbox") {
- // @ts-ignore
- contents.values[name] = element.checked ? "true" : "false";
- } else if (element.getAttribute("type") === "radio") {
- if (element.checked) {
- contents.values[name] = element.value;
- }
- } else {
- // @ts-ignore
- contents.values[name] = element.value ?? element.textContent;
- }
+ if (
+ target.tagName === "FORM" &&
+ (event.type === "submit" || event.type === "input")
+ ) {
+ const formData = new FormData(target);
+
+ for (let name of formData.keys()) {
+ contents.values[name] = formData.getAll(name);
}
}
}
diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs
index e792c977d..e1e3b6365 100644
--- a/packages/web/src/dom.rs
+++ b/packages/web/src/dom.rs
@@ -13,9 +13,10 @@ use dioxus_core::{
use dioxus_html::{event_bubbles, CompositionData, FileEngine, FormData};
use dioxus_interpreter_js::{save_template, Channel};
use futures_channel::mpsc;
+use js_sys::Array;
use rustc_hash::FxHashMap;
use std::{any::Any, rc::Rc, sync::Arc};
-use wasm_bindgen::{closure::Closure, JsCast};
+use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast};
use web_sys::{console, Document, Element, Event, HtmlElement};
use crate::{file_engine::WebFileEngine, Config};
@@ -327,35 +328,16 @@ fn read_input_to_data(target: Element) -> Rc {
// try to fill in form values
if let Some(form) = target.dyn_ref::() {
- let elements = form.elements();
- for x in 0..elements.length() {
- let element = elements.item(x).unwrap();
- if let Some(name) = element.get_attribute("name") {
- let value: Option = element
- .dyn_ref()
- .map(|input: &web_sys::HtmlInputElement| {
- match input.type_().as_str() {
- "checkbox" => {
- match input.checked() {
- true => Some("true".to_string()),
- false => Some("false".to_string()),
- }
- },
- "radio" => {
- match input.checked() {
- true => Some(input.value()),
- false => None,
- }
- }
- _ => Some(input.value())
- }
- })
- .or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlTextAreaElement| Some(input.value())))
- .or_else(|| element.dyn_ref().map(|input: &web_sys::HtmlSelectElement| Some(input.value())))
- .or_else(|| Some(element.dyn_ref::().unwrap().text_content()))
- .expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
- if let Some(value) = value {
- values.insert(name, value);
+ let form_data = get_form_data(form);
+ for value in form_data.entries().into_iter().flatten() {
+ 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 =
+ item_values.iter().filter_map(|v| v.as_string()).collect();
+
+ values.insert(name, item_values);
+ }
}
}
}
@@ -376,6 +358,23 @@ fn read_input_to_data(target: Element) -> Rc {
})
}
+// web-sys does not expose the keys api for form data, so we need to manually bind to it
+#[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));
+ }
+
+ return values;
+ }
+"#)]
+extern "C" {
+ fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map;
+}
+
fn walk_event_for_id(event: &web_sys::Event) -> Option<(ElementId, web_sys::Element)> {
let mut target = event
.target()