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
This commit is contained in:
Miles Murgaw 2023-06-04 12:29:34 -04:00 committed by GitHub
parent 0f684f0567
commit d09c92beda
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 82 additions and 18 deletions

View file

@ -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.

View file

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

View file

@ -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 = []

View file

@ -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);
}
}
}
}

View file

@ -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);
}
}

View file

@ -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>);
}
}

View file

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

View file

@ -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"

View file

@ -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 {