فهرست منبع

Add initial_value attribute & fix static special attribute handling (#1063)

* feat & fix: initial_value attribute, special attribute handling

* revision: rename js file

* fix: rustfmt

* fix: clippy

* fix: desktop not finding common.js

* fix: desktop failing to render

Missed a single ``this.SetAttributeInner`` as it was now ``setAttributeInner``
Javascript didn't even throw any errors about this smh

* revision: no need for match statement
Miles Murgaw 2 سال پیش
والد
کامیت
d09c92beda

+ 7 - 2
packages/desktop/src/protocol.rs

@@ -1,4 +1,4 @@
-use dioxus_interpreter_js::INTERPRETER_JS;
+use dioxus_interpreter_js::{COMMON_JS, INTERPRETER_JS};
 use std::{
     borrow::Cow,
     path::{Path, PathBuf},
@@ -37,7 +37,7 @@ fn module_loader(root_name: &str) -> String {
     );
     format!(
         r#"
-<script>
+<script type="module">
     {js}
 
     let rootname = "{root_name}";
@@ -84,6 +84,11 @@ pub(super) fn desktop_handler(
             .header("Content-Type", "text/html")
             .body(Cow::from(body))
             .map_err(From::from);
+    } else if request.uri().path() == "/common.js" {
+        return Response::builder()
+            .header("Content-Type", "text/javascript")
+            .body(Cow::from(COMMON_JS.as_bytes()))
+            .map_err(From::from);
     }
 
     // Else, try to serve a file from the filesystem.

+ 1 - 0
packages/html/src/elements.rs

@@ -1154,6 +1154,7 @@ builder_constructors! {
         r#type: InputType "type",
         // value: String,
         value: String volatile,
+        initial_value: String DEFAULT,
     };
 
     /// Build a

+ 1 - 0
packages/interpreter/Cargo.toml

@@ -25,3 +25,4 @@ default = []
 serialize = ["serde"]
 web = ["wasm-bindgen", "js-sys", "web-sys"]
 sledgehammer = ["wasm-bindgen", "js-sys", "web-sys", "sledgehammer_bindgen", "sledgehammer_utils"]
+minimal_bindings = []

+ 39 - 0
packages/interpreter/src/common.js

@@ -0,0 +1,39 @@
+export function setAttributeInner(node, field, value, ns) {
+  const name = field;
+  if (ns === "style") {
+    // ????? why do we need to do this
+    if (node.style === undefined) {
+      node.style = {};
+    }
+    node.style[name] = value;
+  } else if (ns != null && ns != undefined) {
+    node.setAttributeNS(ns, name, value);
+  } else {
+    switch (name) {
+      case "value":
+        if (value !== node.value) {
+          node.value = value;
+        }
+        break;
+      case "initial_value":
+        node.defaultValue = value;
+        break;
+      case "checked":
+        node.checked = value === "true" || value === true;
+        break;
+      case "selected":
+        node.selected = value === "true" || value === true;
+        break;
+      case "dangerous_inner_html":
+        node.innerHTML = value;
+        break;
+      default:
+        // https://github.com/facebook/react/blob/8b88ac2592c5f555f315f9440cbb665dd1e7457a/packages/react-dom/src/shared/DOMProperty.js#L352-L364
+        if (value === "false" && bool_attrs.hasOwnProperty(name)) {
+          node.removeAttribute(name);
+        } else {
+          node.setAttribute(name, value);
+        }
+    }
+  }
+}

+ 9 - 4
packages/interpreter/src/interpreter.js

@@ -1,3 +1,5 @@
+import { setAttributeInner } from "./common.js";
+
 class ListenerMap {
   constructor(root) {
     // bubbling events can listen at the root element
@@ -153,10 +155,10 @@ class Interpreter {
       this.RemoveAttribute(id, field, ns);
     } else {
       const node = this.nodes[id];
-      this.SetAttributeInner(node, field, value, ns);
+      setAttributeInner(node, field, value, ns);
     }
   }
-  SetAttributeInner(node, field, value, ns) {
+  /*SetAttributeInner(node, field, value, ns) {
     const name = field;
     if (ns === "style") {
       // ????? why do we need to do this
@@ -173,6 +175,9 @@ class Interpreter {
             node.value = value;
           }
           break;
+        case "initial_value":
+          node.defaultValue = value;
+          break;
         case "checked":
           node.checked = value === "true" || value === true;
           break;
@@ -191,7 +196,7 @@ class Interpreter {
           }
       }
     }
-  }
+  }*/
   RemoveAttribute(root, field, ns) {
     const name = field;
     const node = this.nodes[root];
@@ -291,7 +296,7 @@ class Interpreter {
 
         for (let attr of node.attrs) {
           if (attr.type == "Static") {
-            this.SetAttributeInner(el, attr.name, attr.value, attr.namespace);
+            setAttributeInner(el, attr.name, attr.value, attr.namespace);
           }
         }
 

+ 11 - 0
packages/interpreter/src/lib.rs

@@ -1,4 +1,5 @@
 pub static INTERPRETER_JS: &str = include_str!("./interpreter.js");
+pub static COMMON_JS: &str = include_str!("./common.js");
 
 #[cfg(feature = "sledgehammer")]
 mod sledgehammer_bindings;
@@ -10,3 +11,13 @@ mod bindings;
 
 #[cfg(feature = "web")]
 pub use bindings::Interpreter;
+
+// Common bindings for minimal usage.
+#[cfg(feature = "minimal_bindings")]
+pub mod minimal_bindings {
+    use wasm_bindgen::{prelude::wasm_bindgen, JsValue};
+    #[wasm_bindgen(module = "/src/common.js")]
+    extern "C" {
+        pub fn setAttributeInner(node: JsValue, name: &str, value: JsValue, ns: Option<&str>);
+    }
+}

+ 3 - 0
packages/interpreter/src/sledgehammer_bindings.rs

@@ -74,6 +74,9 @@ mod js {
                         node.value = value;
                     }
                     break;
+                case "initial_value":
+                    node.defaultValue = value;
+                    break;
                 case "checked":
                     node.checked = value === "true";
                     break;

+ 2 - 1
packages/web/Cargo.toml

@@ -14,7 +14,8 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
 dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"] }
 dioxus-html = { path = "../html", version = "^0.3.0", features = ["wasm-bind"] }
 dioxus-interpreter-js = { path = "../interpreter", version = "^0.3.0", features = [
-    "sledgehammer"
+    "sledgehammer",
+    "minimal_bindings",
 ] }
 
 js-sys = "0.3.56"

+ 9 - 11
packages/web/src/dom.rs

@@ -11,13 +11,13 @@ use dioxus_core::{
     BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode,
 };
 use dioxus_html::{event_bubbles, CompositionData, FileEngine, FormData, MountedData};
-use dioxus_interpreter_js::{get_node, save_template, Channel};
+use dioxus_interpreter_js::{get_node, minimal_bindings, 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, prelude::wasm_bindgen, JsCast};
-use web_sys::{console, Document, Element, Event, HtmlElement};
+use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast, JsValue};
+use web_sys::{console, Document, Element, Event};
 
 use crate::{file_engine::WebFileEngine, Config};
 
@@ -135,14 +135,12 @@ impl WebsysDom {
                         namespace,
                     } = attr
                     {
-                        match namespace {
-                            Some(ns) if *ns == "style" => {
-                                el.dyn_ref::<HtmlElement>()
-                                    .map(|f| f.style().set_property(name, value));
-                            }
-                            Some(ns) => el.set_attribute_ns(Some(ns), name, value).unwrap(),
-                            None => el.set_attribute(name, value).unwrap(),
-                        }
+                        minimal_bindings::setAttributeInner(
+                            el.clone().into(),
+                            name,
+                            JsValue::from_str(value),
+                            *namespace,
+                        );
                     }
                 }
                 for child in *children {