{"record":{"id":"7d07671a1884b867","repo":"yewstack/yew","slug":"expected-to-find-a-modal-host-element","errorCode":null,"errorMessage":"Expected to find a #modal_host element","messagePattern":"Expected to find a #modal_host element","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"website/versioned_docs/version-0.22/advanced-topics/portals.mdx","lineNumber":38,"sourceCode":"Note that `yew::create_portal` is a low-level building block. Libraries should use it to implement\nhigher-level APIs which can then be consumed by applications. For example, here is a\nsimple modal dialogue that renders its `children` into an element outside `yew`'s control,\nidentified by the `id=\"modal_host\"`.\n\n```rust\nuse yew::prelude::*;\n\n#[derive(Properties, PartialEq)]\npub struct ModalProps {\n    #[prop_or_default]\n    pub children: Html,\n}\n\n#[component]\nfn Modal(props: &ModalProps) -> Html {\n    let modal_host = gloo::utils::document()\n        .get_element_by_id(\"modal_host\")\n        .expect(\"Expected to find a #modal_host element\");\n\n    create_portal(\n        props.children.clone(),\n        modal_host.into(),\n    )\n}\n```\n\n## Event handling\n\nEvents emitted on elements inside portals follow the virtual DOM when bubbling up. That is,\nif a portal is rendered as the child of an element, then an event listener on that element\nwill catch events dispatched from inside the portal, even if the portal renders its contents\nin an unrelated location in the actual DOM.\n\nThis allows developers to be oblivious of whether a component they consume, is implemented with\nor without portals. Events fired on its children will bubble up regardless.\n","sourceCodeStart":20,"sourceCodeEnd":56,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/website/versioned_docs/version-0.22/advanced-topics/portals.mdx#L20-L56","documentation":"This panic is the `.expect()` after `gloo::utils::document().get_element_by_id(\"modal_host\")` in Yew 0.22's portals guide. `get_element_by_id` returns `Option<Element>` and returns None when the current page markup contains no element with that exact id. The guide requires your static `index.html` to contain the portal destination `<div id=\"modal_host\"></div>` before any `<Modal>` renders into it; the panic means that host element does not exist in the document the code ran against.","triggerScenarios":"Rendering the `<Modal>` component when `index.html` has no element with `id=\"modal_host\"`; the id is misspelled or differently cased (`Modal_host`, `modalhost`); the app shell HTML is produced by a template that omits the host div; or the lookup ran against a document that never contains it.","commonSituations":"Copy-pasting the portals example without editing `index.html`; switching Trunk templates or app shells; `wasm-bindgen-test` suites that render the component into a scratch document; SSR passes where the host div is only added client-side after the first render.","solutions":["Add `<div id=\"modal_host\"></div>` to `index.html` (the static page shell Trunk serves)","Verify the exact id spelling and casing in both `index.html` and the `get_element_by_id` call","If the host may legitimately be absent, replace the expect with `if let Some(host)` and render nothing or a placeholder instead of creating the portal","Make sure the component creating the portal mounts after the DOM is parsed (module scripts / `defer` guarantee this)"],"exampleFix":"// index.html — add the host before the app mounts\n// <body>\n//   <div id=\"modal_host\"></div>\n//   ...\n// </body>\n\n// component — before\nlet modal_host = gloo::utils::document()\n    .get_element_by_id(\"modal_host\")\n    .expect(\"Expected to find a #modal_host element\");\n\n// component — after (fail soft when the host is missing)\nif let Some(modal_host) = gloo::utils::document().get_element_by_id(\"modal_host\") {\n    create_portal(props.children.clone(), modal_host.into())\n} else {\n    html! { <p>{\"modal host #modal_host missing\"}</p> }\n}","handlingStrategy":"validation","validationCode":"fn find_portal_host(id: &str) -> Option<web_sys::Element> {\n    gloo::utils::document().get_element_by_id(id)\n}\n\n// before rendering the Modal component\nif find_portal_host(\"modal_host\").is_none() {\n    gloo::console::warn(\"#modal_host missing in index.html — portal will be skipped\");\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare every required portal host div in index.html next to the app mount point","Keep DOM element ids in one constants module and reuse them in Rust and HTML","Add a startup or e2e assertion that all portal host ids resolve before first render","Ship a helper that returns Option and renders a placeholder instead of calling expect"],"tags":["yew","portals","gloo","dom","panic"],"backgroundTag":"missing-dom-element","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}