{"record":{"id":"71f3229dfde55e81","repo":"yewstack/yew","slug":"expected-to-find-a-modal-host-element-71f322","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.23/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.23/advanced-topics/portals.mdx#L20-L56","documentation":"This panic is the `.expect(\"Expected to find a #modal_host element\")` after `get_element_by_id(\"modal_host\")` in Yew 0.23's portals guide. `get_element_by_id` yields `Option<Element>`, None when no element with that exact id exists in the document. The guide's contract is that your static `index.html` declares the portal destination with `id=\"modal_host\"` before `<Modal>` mounts; the panic signals that contract was not met.","triggerScenarios":"Rendering `<Modal>` when the page shell has no `<div id=\"modal_host\"></div>`; id typo or casing mismatch; the host div removed during a template redesign; tests rendering the component into a document without the host.","commonSituations":"Copy-pasting the 0.23 portals example without editing `index.html`; switching Trunk templates; SSR or hydration setups where the host is added after first render.","solutions":["Add `<div id=\"modal_host\"></div>` to `index.html`","Check the exact id spelling/casing on both sides","Degrade gracefully with `if let Some(host)` and skip or log instead of panicking when the host is missing","Ensure the portal component mounts after DOM parsing (module/defer scripts)"],"exampleFix":"// 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// after\nmatch gloo::utils::document().get_element_by_id(\"modal_host\") {\n    Some(host) => create_portal(props.children.clone(), host.into()),\n    None => html! { <p>{\"missing #modal_host\"}</p> },\n}","handlingStrategy":"validation","validationCode":"if gloo::utils::document().get_element_by_id(\"modal_host\").is_none() {\n    gloo::console::warn(\"#modal_host missing in index.html\");\n    return html! {};\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Declare portal host divs in the static index.html shell","Centralize host ids in constants shared between HTML and Rust","Add a startup check listing every portal host id the app expects","Render a placeholder instead of panicking when a host is absent"],"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"}