Browse Source

Merge pull request #1851 from mirkootter/launchcfg-specify-rootelem

dioxus-web: Add `Config::rootelement`
ealmloff 1 year ago
parent
commit
16c59b8e0b
2 changed files with 44 additions and 17 deletions
  1. 18 3
      packages/web/src/cfg.rs
  2. 26 14
      packages/web/src/dom.rs

+ 18 - 3
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<String>,
     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<String>) -> 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),
+}

+ 26 - 14
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<UiEvent>) -> 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<dyn FnMut(&Event)> = Closure::wrap(Box::new({