diff --git a/packages/interpreter/src/sledgehammer_bindings.rs b/packages/interpreter/src/sledgehammer_bindings.rs index 33f6b4420..650e721ef 100644 --- a/packages/interpreter/src/sledgehammer_bindings.rs +++ b/packages/interpreter/src/sledgehammer_bindings.rs @@ -116,6 +116,10 @@ mod js { export function set_node(id, node) { nodes[id] = node; } + export function get_node(id) { + console.log(nodes, id); + return nodes[id]; + } export function initilize(root, handler) { listeners.handler = handler; nodes = [root]; @@ -166,6 +170,9 @@ mod js { #[wasm_bindgen] pub fn set_node(id: u32, node: Node); + #[wasm_bindgen] + pub fn get_node(id: u32) -> Node; + #[wasm_bindgen] pub fn initilize(root: Node, handler: &Function); } diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 4d17749d8..8aae595eb 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -10,8 +10,8 @@ use dioxus_core::{ BorrowedAttributeValue, ElementId, Mutation, Template, TemplateAttribute, TemplateNode, }; -use dioxus_html::{event_bubbles, CompositionData, FormData}; -use dioxus_interpreter_js::{save_template, Channel}; +use dioxus_html::{event_bubbles, CompositionData, FormData, MountedData}; +use dioxus_interpreter_js::{get_node, save_template, Channel}; use futures_channel::mpsc; use rustc_hash::FxHashMap; use std::{any::Any, rc::Rc}; @@ -27,6 +27,7 @@ pub struct WebsysDom { templates: FxHashMap, max_template_id: u32, pub(crate) interpreter: Channel, + event_channel: mpsc::UnboundedSender, } pub struct UiEvent { @@ -34,7 +35,6 @@ pub struct UiEvent { pub bubbles: bool, pub element: ElementId, pub data: Rc, - pub event: Event, } impl WebsysDom { @@ -48,8 +48,9 @@ impl WebsysDom { }; let interpreter = Channel::default(); - let handler: Closure = - Closure::wrap(Box::new(move |event: &web_sys::Event| { + let handler: Closure = Closure::wrap(Box::new({ + let event_channel = event_channel.clone(); + move |event: &web_sys::Event| { let name = event.type_(); let element = walk_event_for_id(event); let bubbles = dioxus_html::event_bubbles(name.as_str()); @@ -69,10 +70,10 @@ impl WebsysDom { bubbles, element, data, - event: event.clone(), }); } - })); + } + })); dioxus_interpreter_js::initilize( root.clone().unchecked_into(), @@ -85,6 +86,7 @@ impl WebsysDom { interpreter, templates: FxHashMap::default(), max_template_id: 0, + event_channel, } } @@ -156,6 +158,8 @@ impl WebsysDom { pub fn apply_edits(&mut self, mut edits: Vec) { use Mutation::*; let i = &mut self.interpreter; + // we need to apply the mount events last, so we collect them here + let mut to_mount = Vec::new(); for edit in &edits { match edit { AppendChildren { id, m } => i.append_children(id.0 as u32, *m as u32), @@ -206,17 +210,43 @@ impl WebsysDom { }, SetText { value, id } => i.set_text(id.0 as u32, value), NewEventListener { name, id, .. } => { - i.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8); - } - RemoveEventListener { name, id } => { - i.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8) + match *name { + // mounted events are fired immediately after the element is mounted. + "mounted" => { + to_mount.push(*id); + } + _ => { + i.new_event_listener(name, id.0 as u32, event_bubbles(name) as u8); + } + } } + RemoveEventListener { name, id } => match *name { + "mounted" => {} + _ => { + i.remove_event_listener(name, id.0 as u32, event_bubbles(name) as u8); + } + }, Remove { id } => i.remove(id.0 as u32), PushRoot { id } => i.push_root(id.0 as u32), } } edits.clear(); i.flush(); + + for id in to_mount { + let node = get_node(id.0 as u32); + if let Some(element) = node.dyn_ref::() { + log::info!("mounted event fired: {}", id.0); + let data: MountedData = element.into(); + let data = Rc::new(data); + let _ = self.event_channel.unbounded_send(UiEvent { + name: "mounted".to_string(), + bubbles: false, + element: id, + data, + }); + } + } } }