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:
1 parent
0f684f0567
commit
d09c92beda
9 files changed
+82
-18
No files matched your search
@@ -1,4 +1,4 @@
|
|||||||
use dioxus_interpreter_js::INTERPRETER_JS;
|
use dioxus_interpreter_js::{COMMON_JS, INTERPRETER_JS};
|
||||||
use std::{
|
use std::{
|
||||||
borrow::Cow,
|
borrow::Cow,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
@@ -37,7 +37,7 @@ fn module_loader(root_name: &str) -> String {
|
|||||||
);
|
);
|
||||||
format!(
|
format!(
|
||||||
r#"
|
r#"
|
||||||
<script>
|
<script type="module">
|
||||||
{js}
|
{js}
|
||||||
|
|
||||||
let rootname = "{root_name}";
|
let rootname = "{root_name}";
|
||||||
@@ -84,6 +84,11 @@ pub(super) fn desktop_handler(
|
|||||||
.header("Content-Type", "text/html")
|
.header("Content-Type", "text/html")
|
||||||
.body(Cow::from(body))
|
.body(Cow::from(body))
|
||||||
.map_err(From::from);
|
.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.
|
// Else, try to serve a file from the filesystem.
|
||||||
|
|||||||
@@ -1154,6 +1154,7 @@ builder_constructors! {
|
|||||||
r#type: InputType "type",
|
r#type: InputType "type",
|
||||||
// value: String,
|
// value: String,
|
||||||
value: String volatile,
|
value: String volatile,
|
||||||
|
initial_value: String DEFAULT,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Build a
|
/// Build a
|
||||||
|
|||||||
@@ -25,3 +25,4 @@ default = []
|
|||||||
serialize = ["serde"]
|
serialize = ["serde"]
|
||||||
web = ["wasm-bindgen", "js-sys", "web-sys"]
|
web = ["wasm-bindgen", "js-sys", "web-sys"]
|
||||||
sledgehammer = ["wasm-bindgen", "js-sys", "web-sys", "sledgehammer_bindgen", "sledgehammer_utils"]
|
sledgehammer = ["wasm-bindgen", "js-sys", "web-sys", "sledgehammer_bindgen", "sledgehammer_utils"]
|
||||||
|
minimal_bindings = []
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { setAttributeInner } from "./common.js";
|
||||||
|
|
||||||
class ListenerMap {
|
class ListenerMap {
|
||||||
constructor(root) {
|
constructor(root) {
|
||||||
// bubbling events can listen at the root element
|
// bubbling events can listen at the root element
|
||||||
@@ -153,10 +155,10 @@ class Interpreter {
|
|||||||
this.RemoveAttribute(id, field, ns);
|
this.RemoveAttribute(id, field, ns);
|
||||||
} else {
|
} else {
|
||||||
const node = this.nodes[id];
|
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;
|
const name = field;
|
||||||
if (ns === "style") {
|
if (ns === "style") {
|
||||||
// ????? why do we need to do this
|
// ????? why do we need to do this
|
||||||
@@ -173,6 +175,9 @@ class Interpreter {
|
|||||||
node.value = value;
|
node.value = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "initial_value":
|
||||||
|
node.defaultValue = value;
|
||||||
|
break;
|
||||||
case "checked":
|
case "checked":
|
||||||
node.checked = value === "true" || value === true;
|
node.checked = value === "true" || value === true;
|
||||||
break;
|
break;
|
||||||
@@ -191,7 +196,7 @@ class Interpreter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
RemoveAttribute(root, field, ns) {
|
RemoveAttribute(root, field, ns) {
|
||||||
const name = field;
|
const name = field;
|
||||||
const node = this.nodes[root];
|
const node = this.nodes[root];
|
||||||
@@ -291,7 +296,7 @@ class Interpreter {
|
|||||||
|
|
||||||
for (let attr of node.attrs) {
|
for (let attr of node.attrs) {
|
||||||
if (attr.type == "Static") {
|
if (attr.type == "Static") {
|
||||||
this.SetAttributeInner(el, attr.name, attr.value, attr.namespace);
|
setAttributeInner(el, attr.name, attr.value, attr.namespace);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
pub static INTERPRETER_JS: &str = include_str!("./interpreter.js");
|
pub static INTERPRETER_JS: &str = include_str!("./interpreter.js");
|
||||||
|
pub static COMMON_JS: &str = include_str!("./common.js");
|
||||||
|
|
||||||
#[cfg(feature = "sledgehammer")]
|
#[cfg(feature = "sledgehammer")]
|
||||||
mod sledgehammer_bindings;
|
mod sledgehammer_bindings;
|
||||||
@@ -10,3 +11,13 @@ mod bindings;
|
|||||||
|
|
||||||
#[cfg(feature = "web")]
|
#[cfg(feature = "web")]
|
||||||
pub use bindings::Interpreter;
|
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>);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -74,6 +74,9 @@ mod js {
|
|||||||
node.value = value;
|
node.value = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case "initial_value":
|
||||||
|
node.defaultValue = value;
|
||||||
|
break;
|
||||||
case "checked":
|
case "checked":
|
||||||
node.checked = value === "true";
|
node.checked = value === "true";
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ keywords = ["dom", "ui", "gui", "react", "wasm"]
|
|||||||
dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"] }
|
dioxus-core = { path = "../core", version = "^0.3.0", features = ["serialize"] }
|
||||||
dioxus-html = { path = "../html", version = "^0.3.0", features = ["wasm-bind"] }
|
dioxus-html = { path = "../html", version = "^0.3.0", features = ["wasm-bind"] }
|
||||||
dioxus-interpreter-js = { path = "../interpreter", version = "^0.3.0", features = [
|
dioxus-interpreter-js = { path = "../interpreter", version = "^0.3.0", features = [
|
||||||
"sledgehammer"
|
"sledgehammer",
|
||||||
|
"minimal_bindings",
|
||||||
] }
|
] }
|
||||||
|
|
||||||
js-sys = "0.3.56"
|
js-sys = "0.3.56"
|
||||||
|
|||||||
+9
-11
@@ -11,13 +11,13 @@ use dioxus_core::{
|
|||||||
BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode,
|
BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode,
|
||||||
};
|
};
|
||||||
use dioxus_html::{event_bubbles, CompositionData, FileEngine, FormData, MountedData};
|
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 futures_channel::mpsc;
|
||||||
use js_sys::Array;
|
use js_sys::Array;
|
||||||
use rustc_hash::FxHashMap;
|
use rustc_hash::FxHashMap;
|
||||||
use std::{any::Any, rc::Rc, sync::Arc};
|
use std::{any::Any, rc::Rc, sync::Arc};
|
||||||
use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast};
|
use wasm_bindgen::{closure::Closure, prelude::wasm_bindgen, JsCast, JsValue};
|
||||||
use web_sys::{console, Document, Element, Event, HtmlElement};
|
use web_sys::{console, Document, Element, Event};
|
||||||
|
|
||||||
use crate::{file_engine::WebFileEngine, Config};
|
use crate::{file_engine::WebFileEngine, Config};
|
||||||
|
|
||||||
@@ -135,14 +135,12 @@ impl WebsysDom {
|
|||||||
namespace,
|
namespace,
|
||||||
} = attr
|
} = attr
|
||||||
{
|
{
|
||||||
match namespace {
|
minimal_bindings::setAttributeInner(
|
||||||
Some(ns) if *ns == "style" => {
|
el.clone().into(),
|
||||||
el.dyn_ref::<HtmlElement>()
|
name,
|
||||||
.map(|f| f.style().set_property(name, value));
|
JsValue::from_str(value),
|
||||||
}
|
*namespace,
|
||||||
Some(ns) => el.set_attribute_ns(Some(ns), name, value).unwrap(),
|
);
|
||||||
None => el.set_attribute(name, value).unwrap(),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for child in *children {
|
for child in *children {
|
||||||
|
|||||||
Reference in new issue
Block a user