mirror of
https://github.com/DioxusLabs/dioxus
synced 2024-11-26 14:10:20 +00:00
Merge branch 'fix-select-form-events' into implement-file-engine
This commit is contained in:
commit
6d3d927d5c
3 changed files with 39 additions and 47 deletions
|
@ -10,7 +10,7 @@ pub type FormEvent = Event<FormData>;
|
|||
pub struct FormData {
|
||||
pub value: String,
|
||||
|
||||
pub values: HashMap<String, String>,
|
||||
pub values: HashMap<String, Vec<String>>,
|
||||
|
||||
#[cfg_attr(feature = "serialize", serde(skip))]
|
||||
pub files: Option<std::sync::Arc<dyn FileEngine>>,
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<FormData> {
|
|||
|
||||
// try to fill in form values
|
||||
if let Some(form) = target.dyn_ref::<web_sys::HtmlFormElement>() {
|
||||
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<String> = 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()),
|
||||
let form_data = get_form_data(form);
|
||||
for value in form_data.entries().into_iter().flatten() {
|
||||
if let Ok(array) = value.dyn_into::<Array>() {
|
||||
if let Some(name) = array.get(0).as_string() {
|
||||
if let Ok(item_values) = array.get(1).dyn_into::<Array>() {
|
||||
let item_values =
|
||||
item_values.iter().filter_map(|v| v.as_string()).collect();
|
||||
|
||||
values.insert(name, item_values);
|
||||
}
|
||||
},
|
||||
"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::<web_sys::HtmlElement>().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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -376,6 +358,23 @@ fn read_input_to_data(target: Element) -> Rc<FormData> {
|
|||
})
|
||||
}
|
||||
|
||||
// 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()
|
||||
|
|
Loading…
Reference in a new issue