From f66d17ca84f80f199e5ce1735a11f087af7fe4ea Mon Sep 17 00:00:00 2001 From: Jonathan Kelley Date: Sat, 22 Jan 2022 14:53:59 -0500 Subject: [PATCH] wip: pass form data between web and desktop --- examples/form.rs | 23 +++++++++++++++++++++++ packages/html/src/events.rs | 3 +++ packages/jsinterpreter/interpreter.js | 18 ++++++++++++++++++ packages/jsinterpreter/interpreter.ts | 24 ++++++++++++++++++++---- packages/web/Cargo.toml | 1 + packages/web/src/dom.rs | 7 +++---- 6 files changed, 68 insertions(+), 8 deletions(-) create mode 100644 examples/form.rs diff --git a/examples/form.rs b/examples/form.rs new file mode 100644 index 000000000..577658aeb --- /dev/null +++ b/examples/form.rs @@ -0,0 +1,23 @@ +//! Example: README.md showcase +//! +//! The example from the README.md. + +use dioxus::prelude::*; + +fn main() { + dioxus::desktop::launch(app); +} + +fn app(cx: Scope) -> Element { + cx.render(rsx! { + div { + h1 { "Form" } + form { + oninput: move |ev| println!("{:?}", ev), + input { r#type: "text", name: "username" } + input { r#type: "text", name: "full-name" } + input { r#type: "password", name: "password" } + } + } + }) +} diff --git a/packages/html/src/events.rs b/packages/html/src/events.rs index b9bcecd4f..8067e6314 100644 --- a/packages/html/src/events.rs +++ b/packages/html/src/events.rs @@ -3,6 +3,8 @@ use dioxus_core::exports::bumpalo; use dioxus_core::*; pub mod on { + use std::collections::HashMap; + use super::*; macro_rules! event_directory { ( $( @@ -484,6 +486,7 @@ pub mod on { #[derive(Debug)] pub struct FormData { pub value: String, + pub values: HashMap, /* DOMEvent: Send + SyncTarget relatedTarget */ } diff --git a/packages/jsinterpreter/interpreter.js b/packages/jsinterpreter/interpreter.js index ea50ec3d3..09cfa194b 100644 --- a/packages/jsinterpreter/interpreter.js +++ b/packages/jsinterpreter/interpreter.js @@ -231,6 +231,23 @@ export class Interpreter { } } } + if (target.tagName == "FORM") { + let formTarget = target; + for (let x = 0; x < formTarget.elements.length; x++) { + let element = formTarget.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 { + // @ts-ignore + contents.values[name] = element.value ?? element.textContent; + } + } + } + } if (realId == null) { return; } @@ -316,6 +333,7 @@ function serialize_event(event) { } return { value: value, + values: {} }; } case "click": diff --git a/packages/jsinterpreter/interpreter.ts b/packages/jsinterpreter/interpreter.ts index fdd8c671d..744f91081 100644 --- a/packages/jsinterpreter/interpreter.ts +++ b/packages/jsinterpreter/interpreter.ts @@ -244,7 +244,6 @@ export class Interpreter { break; case "NewEventListener": - // this handler is only provided on desktop implementations since this // method is not used by the web implementation let handler = (event: Event) => { @@ -286,6 +285,23 @@ export class Interpreter { } } + if (target.tagName == "FORM") { + let formTarget = target as HTMLFormElement; + for (let x = 0; x < formTarget.elements.length; x++) { + let element = formTarget.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 { + // @ts-ignore + contents.values[name] = element.value ?? element.textContent; + } + } + } + } + if (realId == null) { return; } @@ -385,6 +401,8 @@ function serialize_event(event: Event) { case "invalid": case "reset": case "submit": { + + let target = event.target as HTMLFormElement; let value = target.value ?? target.textContent; @@ -394,6 +412,7 @@ function serialize_event(event: Event) { return { value: value, + values: {} }; } @@ -643,8 +662,6 @@ const bool_attrs = { truespeed: true, }; - - type PushRoot = { type: "PushRoot", root: number }; type AppendChildren = { type: "AppendChildren", many: number }; type ReplaceWith = { type: "ReplaceWith", root: number, m: number }; @@ -661,7 +678,6 @@ type SetText = { type: "SetText", root: number, text: string }; type SetAttribute = { type: "SetAttribute", root: number, field: string, value: string, ns: string | undefined }; type RemoveAttribute = { type: "RemoveAttribute", root: number, name: string }; - type DomEdit = PushRoot | AppendChildren | diff --git a/packages/web/Cargo.toml b/packages/web/Cargo.toml index 52a78e631..6acdb5366 100644 --- a/packages/web/Cargo.toml +++ b/packages/web/Cargo.toml @@ -41,6 +41,7 @@ features = [ "HtmlInputElement", "HtmlSelectElement", "HtmlTextAreaElement", + "HtmlFormElement", "EventTarget", "HtmlCollection", "Node", diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index ffbef9f4b..b60f2485d 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -178,7 +178,8 @@ fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc anyhow::Result { priority: dioxus_core::EventPriority::Medium, }); } - Some(Err(e)) => { - return Err(e.into()); - } + Some(Err(e)) => return Err(e.into()), None => { // walk the tree upwards until we actually find an event target if let Some(parent) = target.parent_element() {