diff --git a/packages/web/src/cfg.rs b/packages/web/src/cfg.rs index 7483a7a8b..db6695035 100644 --- a/packages/web/src/cfg.rs +++ b/packages/web/src/cfg.rs @@ -10,7 +10,7 @@ pub struct Config { #[cfg(feature = "hydrate")] pub(crate) hydrate: bool, - pub(crate) rootname: String, + pub(crate) root: ConfigRoot, pub(crate) cached_strings: Vec, pub(crate) default_panic_hook: bool, } @@ -20,7 +20,7 @@ impl Default for Config { Self { #[cfg(feature = "hydrate")] hydrate: false, - rootname: "main".to_string(), + root: ConfigRoot::RootName("main".to_string()), cached_strings: Vec::new(), default_panic_hook: true, } @@ -50,8 +50,18 @@ impl Config { /// Set the name of the element that Dioxus will use as the root. /// /// This is akin to calling React.render() on the element with the specified name. + /// Note that this only works on the current document, i.e. `window.document`. + /// To use a different document (popup, iframe, ...) use [Self::rootelement] instead. pub fn rootname(mut self, name: impl Into) -> Self { - self.rootname = name.into(); + self.root = ConfigRoot::RootName(name.into()); + self + } + + /// Set the element that Dioxus will use as root. + /// + /// This is akin to calling React.render() on the given element. + pub fn rootelement(mut self, elem: web_sys::Element) -> Self { + self.root = ConfigRoot::RootElement(elem); self } @@ -72,3 +82,8 @@ impl Config { self } } + +pub(crate) enum ConfigRoot { + RootName(String), + RootElement(web_sys::Element), +} diff --git a/packages/web/src/dom.rs b/packages/web/src/dom.rs index 44c0628e6..94cc03c9e 100644 --- a/packages/web/src/dom.rs +++ b/packages/web/src/dom.rs @@ -37,24 +37,36 @@ pub struct UiEvent { pub data: PlatformEventData, } +//fn get_document(elem: &web_sys::Element) -> + impl WebsysDom { pub fn new(cfg: Config, event_channel: mpsc::UnboundedSender) -> Self { - // eventually, we just want to let the interpreter do all the work of decoding events into our event type - // a match here in order to avoid some error during runtime browser test - let document = load_document(); - let root = match document.get_element_by_id(&cfg.rootname) { - Some(root) => root, - None => { - web_sys::console::error_1( - &format!( - "element '#{}' not found. mounting to the body.", - cfg.rootname - ) - .into(), - ); - document.create_element("body").ok().unwrap() + let (document, root) = match cfg.root { + crate::cfg::ConfigRoot::RootName(rootname) => { + // eventually, we just want to let the interpreter do all the work of decoding events into our event type + // a match here in order to avoid some error during runtime browser test + let document = load_document(); + let root = match document.get_element_by_id(&rootname) { + Some(root) => root, + None => { + web_sys::console::error_1( + &format!("element '#{}' not found. mounting to the body.", rootname) + .into(), + ); + document.create_element("body").ok().unwrap() + } + }; + (document, root) + } + crate::cfg::ConfigRoot::RootElement(root) => { + let document = match root.owner_document() { + Some(document) => document, + None => load_document(), + }; + (document, root) } }; + let interpreter = Channel::default(); let handler: Closure = Closure::wrap(Box::new({