{"record":{"id":"0baeaf0f58eda08f","repo":"yewstack/yew","slug":"event-target-should-be-of-type-htmlelement-0baeaf","errorCode":null,"errorMessage":"event target should be of type HtmlElement","messagePattern":"event target should be of type HtmlElement","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"website/versioned_docs/version-0.23/concepts/basic-web-technologies/web-sys.mdx","lineNumber":174,"sourceCode":"features = [\n    \"console\",\n    \"Document\",\n    \"HtmlElement\",\n    \"MouseEvent\",\n    \"DomRect\",\n]\n```\n\n```rust ,no_run\nuse wasm_bindgen::{prelude::Closure, JsCast};\nuse web_sys::{console, Document, HtmlElement, MouseEvent};\n\nlet mousemove = Closure::<dyn Fn(MouseEvent)>::wrap(Box::new(|e: MouseEvent| {\n    let rect = e\n        .target()\n        .expect(\"mouse event doesn't have a target\")\n        .dyn_into::<HtmlElement>()\n        .expect(\"event target should be of type HtmlElement\")\n        .get_bounding_client_rect();\n    let x = (e.client_x() as f64) - rect.left();\n    let y = (e.client_y() as f64) - rect.top();\n    console::log_1(&format!(\"Left? : {} ; Top? : {}\", x, y).into());\n}));\n\nDocument::new()\n    .expect(\"global document not set\")\n    .get_element_by_id(\"mousemoveme\")\n    .expect(\"element with id `mousemoveme` not present\")\n    .unchecked_into::<HtmlElement>()\n    .set_onmousemove(mousemove.as_ref().dyn_ref());\n\n// we now need to save the `mousemove` Closure so that when\n// this event fires the closure is still in memory.\n```\n\nThis version is much more verbose, but you will probably notice part of that is because of failure","sourceCodeStart":156,"sourceCodeEnd":192,"githubUrl":"https://github.com/yewstack/yew/blob/0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3/website/versioned_docs/version-0.23/concepts/basic-web-technologies/web-sys.mdx#L156-L192","documentation":"This panic is `.dyn_into::<HtmlElement>().expect(\"event target should be of type HtmlElement\")` in Yew 0.23's web-sys mousemove example. `JsCast::dyn_into` returns `Err(EventTarget)` when the target is not an `HtmlElement` JS instance. `e.target()` is the deepest node under the pointer, so the cast fails when the listener is bound to `document`/`window` (target is a Document/Window) or when the pointer is over an SVG descendant (target is `SvgElement`).","triggerScenarios":"Binding `onmousemove` on `document` or `window` for full-page tracking; pointer hovering `<svg>`/`<canvas>`/MathML children whose JS type is not HtmlElement; synthetic events dispatched on the document node.","commonSituations":"Extending the guide's snippet to page-level tracking; icon-heavy layouts inside the tracked element; test dispatch on non-element nodes.","solutions":["Use `target.dyn_ref::<HtmlElement>()` in an `if let` and skip non-HTML-element targets","Use `e.current_target()` — the element the handler is attached to — so the `HtmlElement` cast always succeeds","When listening on document by design, `match` on `dyn_into` and handle both arms"],"exampleFix":"// before\n.dyn_into::<HtmlElement>()\n.expect(\"event target should be of type HtmlElement\")\n.get_bounding_client_rect();\n\n// after\nlet rect = e\n    .current_target()\n    .dyn_into::<HtmlElement>()\n    .ok()?\n    .get_bounding_client_rect();","handlingStrategy":"type-guard","validationCode":"let t = e.current_target();\nif !t.is_instance_of::<web_sys::HtmlElement>() {\n    return;\n}\nlet rect = t.unchecked_ref::<web_sys::HtmlElement>().get_bounding_client_rect();","typeGuard":"use wasm_bindgen::JsCast;\nuse web_sys::{EventTarget, HtmlElement};\n\nfn is_html_element(t: &EventTarget) -> bool {\n    t.is_instance_of::<HtmlElement>()\n}","tryCatchPattern":null,"preventionTips":["Bind mousemove to the element you track and use current_target() — the cast is then always valid","Use dyn_ref::<HtmlElement>() with if-let for target() results","Account for SvgElement targets when the tracked area contains SVG","Match on dyn_into's Result when listening on document/window"],"tags":["web-sys","jscast","events","type-mismatch","panic"],"backgroundTag":"runtime-type-cast-failed","analyzedSha":"0e4a05472fac4e5fce1befe60fa4a1e43a36b6a3","analyzedAt":"2026-08-22T21:16:31.212Z","schemaVersion":2},"datasetVersion":"2026-08-23T01:17:44.959Z"}