Forráskód Böngészése

wip: pass form data between web and desktop

Jonathan Kelley 3 éve
szülő
commit
f66d17ca84

+ 23 - 0
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" }
+            }
+        }
+    })
+}

+ 3 - 0
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<String, String>,
         /* DOMEvent:  Send + SyncTarget relatedTarget */
     }
 

+ 18 - 0
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":

+ 20 - 4
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 |

+ 1 - 0
packages/web/Cargo.toml

@@ -41,6 +41,7 @@ features = [
     "HtmlInputElement",
     "HtmlSelectElement",
     "HtmlTextAreaElement",
+    "HtmlFormElement",
     "EventTarget",
     "HtmlCollection",
     "Node",

+ 3 - 4
packages/web/src/dom.rs

@@ -178,7 +178,8 @@ fn virtual_event_from_websys_event(event: web_sys::Event) -> Arc<dyn Any + Send
                 })
                 .expect("only an InputElement or TextAreaElement or an element with contenteditable=true can have an oninput event listener");
 
-            Arc::new(FormData { value })
+            let values = std::collections::HashMap::new();
+            Arc::new(FormData { value, values })
         }
         "click" | "contextmenu" | "doubleclick" | "drag" | "dragend" | "dragenter" | "dragexit"
         | "dragleave" | "dragover" | "dragstart" | "drop" | "mousedown" | "mouseenter"
@@ -296,9 +297,7 @@ fn decode_trigger(event: &web_sys::Event) -> anyhow::Result<UserEvent> {
                     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() {