diff --git a/packages/cli/src/builder.rs b/packages/cli/src/builder.rs index 92d9ab093..6ad009bd9 100644 --- a/packages/cli/src/builder.rs +++ b/packages/cli/src/builder.rs @@ -117,8 +117,13 @@ pub fn build(config: &CrateConfig, _: bool, skip_assets: bool) -> Result Result target_dir - .join(format!("wasm32-unknown-unknown/{}", build_profile)) + .join(format!("wasm32-unknown-unknown/{}", build_target)) .join(format!("{}.wasm", name)), ExecutableType::Example(name) => target_dir - .join(format!("wasm32-unknown-unknown/{}/examples", build_profile)) + .join(format!("wasm32-unknown-unknown/{}/examples", build_target)) .join(format!("{}.wasm", name)), }; diff --git a/packages/desktop/headless_tests/events.rs b/packages/desktop/headless_tests/events.rs index a473611bb..45daa2f89 100644 --- a/packages/desktop/headless_tests/events.rs +++ b/packages/desktop/headless_tests/events.rs @@ -204,13 +204,27 @@ fn app() -> Element { r#"new FocusEvent("focusout",{bubbles: true})"#, ); - if **received_events == 12 { + if **received_events == 13 { println!("all events recieved"); desktop_context.close(); } render! { div { + div { + width: "100px", + height: "100px", + onmounted: move |evt| { + to_owned![received_events]; + async move { + let rect = evt.get_client_rect().await.unwrap(); + println!("rect: {:?}", rect); + assert_eq!(rect.width(), 100.0); + assert_eq!(rect.height(), 100.0); + received_events.modify(|x| *x + 1) + } + } + } button { id: "button", onclick: move |event| { diff --git a/packages/liveview/src/pool.rs b/packages/liveview/src/pool.rs index 72635c1d0..acc128c32 100644 --- a/packages/liveview/src/pool.rs +++ b/packages/liveview/src/pool.rs @@ -6,7 +6,7 @@ use crate::{ LiveViewError, }; use dioxus_core::prelude::*; -use dioxus_html::{EventData, HtmlEvent, MountedData, PlatformEventData}; +use dioxus_html::{EventData, HtmlEvent, PlatformEventData}; use dioxus_interpreter_js::MutationState; use futures_util::{pin_mut, SinkExt, StreamExt}; use serde::Serialize; @@ -182,7 +182,7 @@ pub async fn run(mut vdom: VirtualDom, ws: impl LiveViewSocket) -> Result<(), Li let element = LiveviewElement::new(evt.element, query_engine.clone()); vdom.handle_event( &evt.name, - Rc::new(PlatformEventData::new(Box::new(MountedData::new(element)))), + Rc::new(PlatformEventData::new(Box::new(element))), evt.element, evt.bubbles, ); diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 6e2ecc29b..488e3b487 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -25,6 +25,8 @@ pub struct WebsysDom { pub(crate) interpreter: Channel, #[cfg(feature = "mounted")] pub(crate) event_channel: mpsc::UnboundedSender, + #[cfg(feature = "mounted")] + pub(crate) queued_mounted_events: Vec, } pub struct UiEvent { @@ -109,6 +111,8 @@ impl WebsysDom { max_template_id: 0, #[cfg(feature = "mounted")] event_channel, + #[cfg(feature = "mounted")] + queued_mounted_events: Default::default(), } } diff --git a/packages/web/src/eval.rs b/packages/web/src/eval.rs index c1b4a7c6b..3c65b900d 100644 --- a/packages/web/src/eval.rs +++ b/packages/web/src/eval.rs @@ -86,7 +86,7 @@ impl WebEvaluator { Ok(Self { dioxus, - channel_receiver: channel_receiver, + channel_receiver, result: RefCell::new(Some(result)), }) } diff --git a/packages/web/src/event.rs b/packages/web/src/event.rs index 9e5ca9421..2e9632eae 100644 --- a/packages/web/src/event.rs +++ b/packages/web/src/event.rs @@ -410,6 +410,12 @@ impl HasFormData for WebFormData { } } + // try to fill in select element values + if let Some(select) = self.element.dyn_ref::() { + let options = get_select_data(select); + values.insert("options".to_string(), FormValue::VecText(options)); + } + values } @@ -530,16 +536,17 @@ export function get_form_data(form) { const formData = new FormData(form); for (let name of formData.keys()) { - const fieldType = target.elements[name].type; + const fieldType = form.elements[name].type; + console.log(fieldType); switch (fieldType) { case "select-multiple": - contents.values[name] = formData.getAll(name); + values.set(name, formData.getAll(name)); break; // add cases for fieldTypes that can hold multiple values here default: - contents.values[name] = formData.get(name); + values.set(name, formData.get(name)); break; } } @@ -550,3 +557,21 @@ export function get_form_data(form) { extern "C" { fn get_form_data(form: &web_sys::HtmlFormElement) -> js_sys::Map; } + +// web-sys does not expose the keys api for select data, so we need to manually bind to it +#[wasm_bindgen(inline_js = r#" +export function get_select_data(select) { + let values = []; + for (let i = 0; i < select.options.length; i++) { + let option = select.options[i]; + if (option.selected) { + values.push(option.value.toString()); + } + } + + return values; +} +"#)] +extern "C" { + fn get_select_data(select: &web_sys::HtmlSelectElement) -> Vec; +} diff --git a/packages/web/src/mutations.rs b/packages/web/src/mutations.rs index 8e050e40f..3a5ac4334 100644 --- a/packages/web/src/mutations.rs +++ b/packages/web/src/mutations.rs @@ -4,7 +4,6 @@ use dioxus_core::prelude::*; use dioxus_core::WriteMutations; use dioxus_core::{AttributeValue, ElementId}; use dioxus_html::event_bubbles; -use dioxus_html::MountedData; use dioxus_html::PlatformEventData; use dioxus_interpreter_js::get_node; use dioxus_interpreter_js::minimal_bindings; @@ -58,22 +57,27 @@ impl WebsysDom { } pub fn flush_edits(&mut self) { - self.interpreter.flush() + self.interpreter.flush(); + #[cfg(feature = "mounted")] + // Now that we've flushed the edits and the dom nodes exist, we can send the mounted events. + { + for id in self.queued_mounted_events.drain(..) { + let node = get_node(id.0 as u32); + if let Some(element) = node.dyn_ref::() { + let _ = self.event_channel.unbounded_send(UiEvent { + name: "mounted".to_string(), + bubbles: false, + element: id, + data: PlatformEventData::new(Box::new(element.clone())), + }); + } + } + } } #[cfg(feature = "mounted")] - pub(crate) fn send_mount_event(&self, id: ElementId) { - let node = get_node(id.0 as u32); - if let Some(element) = node.dyn_ref::() { - let data: MountedData = element.into(); - let data = Box::new(data); - let _ = self.event_channel.unbounded_send(UiEvent { - name: "mounted".to_string(), - bubbles: false, - element: id, - data: PlatformEventData::new(data), - }); - } + pub(crate) fn send_mount_event(&mut self, id: ElementId) { + self.queued_mounted_events.push(id); } } diff --git a/playwright-tests/liveview/src/main.rs b/playwright-tests/liveview/src/main.rs index e6fb46955..b834b6842 100644 --- a/playwright-tests/liveview/src/main.rs +++ b/playwright-tests/liveview/src/main.rs @@ -11,29 +11,15 @@ fn app() -> Element { "hello axum! {num}" button { onclick: move |_| num += 1, "Increment" } } - svg { - circle { cx: 50, cy: 50, r: 40, stroke: "green", fill: "yellow" } - } - div { - class: "raw-attribute-div", - "raw-attribute": "raw-attribute-value", - } - div { - class: "hidden-attribute-div", - hidden: true, - } + svg { circle { cx: 50, cy: 50, r: 40, stroke: "green", fill: "yellow" } } + div { class: "raw-attribute-div", "raw-attribute": "raw-attribute-value" } + div { class: "hidden-attribute-div", hidden: true } div { class: "dangerous-inner-html-div", - dangerous_inner_html: "

hello dangerous inner html

", - } - input { - value: "hello input", - } - div { - class: "style-div", - color: "red", - "colored text" + dangerous_inner_html: "

hello dangerous inner html

" } + input { value: "hello input" } + div { class: "style-div", color: "red", "colored text" } }) } diff --git a/playwright-tests/web/src/main.rs b/playwright-tests/web/src/main.rs index 2e7126ad3..a3a3cc71e 100644 --- a/playwright-tests/web/src/main.rs +++ b/playwright-tests/web/src/main.rs @@ -11,57 +11,38 @@ fn app() -> Element { rsx! { div { "hello axum! {num}" - button { - class: "increment-button", - onclick: move |_| num += 1, "Increment" - } - } - svg { - circle { cx: 50, cy: 50, r: 40, stroke: "green", fill: "yellow" } - } - div { - class: "raw-attribute-div", - "raw-attribute": "raw-attribute-value", - } - div { - class: "hidden-attribute-div", - hidden: true, + button { class: "increment-button", onclick: move |_| num += 1, "Increment" } } + svg { circle { cx: 50, cy: 50, r: 40, stroke: "green", fill: "yellow" } } + div { class: "raw-attribute-div", "raw-attribute": "raw-attribute-value" } + div { class: "hidden-attribute-div", hidden: true } div { class: "dangerous-inner-html-div", - dangerous_inner_html: "

hello dangerous inner html

", - } - input { - value: "hello input", - } - div { - class: "style-div", - color: "red", - "colored text" + dangerous_inner_html: "

hello dangerous inner html

" } + input { value: "hello input" } + div { class: "style-div", color: "red", "colored text" } button { class: "eval-button", onclick: move |_| { let eval = eval_provider( - r#" - window.document.title = 'Hello from Dioxus Eval!'; - dioxus.send("returned eval value"); - "#).unwrap(); + r#" + window.document.title = 'Hello from Dioxus Eval!'; + dioxus.send("returned eval value"); + "#, + ) + .unwrap(); let setter = eval_result.setter(); async move { - // Set the window title let result = eval.recv().await; if let Ok(serde_json::Value::String(string)) = result { setter(string); } - - }}, + } + }, "Eval" } - div { - class: "eval-result", - "{eval_result}" - } + div { class: "eval-result", "{eval_result}" } }) }