Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

dioxus-web: Add Config::rootelement #1851

Merged
merged 1 commit into from Jan 20, 2024

Conversation

mirkootter
Copy link
Contributor

This PR affects dioxus-web and allows to specify a direct element as dom-root. Before, it was necessary to specify the element by ID. This is annoying, for example if the element was created dynamically.

It is now possible to directly specify the element:

let doc = web_sys::window().unwrap().document().unwrap();
let elem = doc.get_element_by_id("main").unwrap();

use dioxus_web::Config;
dioxus_web::launch_cfg(App, Config::new().rootelement(elem));

This is equivalent to

use dioxus_web::Config;
dioxus_web::launch_cfg(App, Config::new().rootname("main"));

The old approaches still work. This PR just adds the new method Config::rootelement. It is necessary for dynamically created elements, for example in shadow roots.

Open problems

Unfortunately, it still does not work with iframes and popup windows, because of a nice JavaScript detail: JavaScript types like Object, Element, Node, ... are tied to a window. Therefore, JavaScript code like the following will print "false":

let iframe = /* ... */;
let elem = iframe.content_document.get_element_by_id("main");
console.log(elem instanceOf Element); // false :(

This behaviour obviously transfers to WASM, i.e. the following code panics:

let iframe: web_sys::HtmlIFrameElement = /* ... */;
let document = iframe.content_document().unwrap(); // ok, but tied to another window
let body = document.body().unwrap(); // ok, HtmlElement
let body: web_sys::Element = body.dyn_into().unwrap(); // panics :(

The last line is necessary because we need to cast HtmlElement to Element. Unfortunately, this does not work, because rust does not support "Runtime types", for example types which are tied to specific windows which are created at runtime.

Note that the problem is only caused by the fact that dyn_into uses the instanceOf operator to check if the cast is ok. Just using body.into() works fine. I adjusted all places in dioxus-web, and it worked fine with both iframes and popup windows 馃殌馃殌馃殌

However, this may be a little too risky for this PR. Maybe I'll add another after this one.

Issues

Closes #1848

@ealmloff
Copy link
Member

ealmloff commented Jan 20, 2024

Note that the problem is only caused by the fact that dyn_into uses the instanceOf operator to check if the cast is ok. Just using body.into() works fine. I adjusted all places in dioxus-web, and it worked fine with both iframes and popup windows 馃殌馃殌馃殌

That seems like a good solution, feel free to include it in another PR

Copy link
Member

@ealmloff ealmloff left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks great, thank you!

@ealmloff ealmloff merged commit 16c59b8 into DioxusLabs:master Jan 20, 2024
10 checks passed
@mirkootter mirkootter deleted the launchcfg-specify-rootelem branch January 20, 2024 14:54
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

web renderer: Allow passing a web_sys::Element to launch_cfg
2 participants