Responding to Events in Dioxus
A complete guide on how to handle interactions using Dioxus Rust syntax. This covers all 93 available events, mapping each to its specific virtual DOM element and providing an independent rsx! example.
Form & Input Events
oninput
Targets: inputtextareaselect
Fires immediately as the user modifies the value. Used for controlled components.
rsx! {
input {
oninput: move |event| text.set(event.value()),
value: "{text}"
}
}
onchange
Targets: inputtextareaselect
Fires when the element loses focus after its value was changed.
rsx! {
select {
onchange: move |event| handle_selection(event.value()),
option { "A" }
}
}
oninvalid
Targets: inputform
Fires when constraint validation fails during form submission.
rsx! {
input {
required: "true",
oninvalid: move |_| show_error.set(true)
}
}
onsubmit
Targets: form
Fires when a form is submitted. Always remember to call prevent_default() in web apps.
rsx! {
form {
onsubmit: move |event| {
event.prevent_default();
send_to_api(event.values());
},
button { type: "submit", "Send" }
}
}
onreset
Targets: form
Fires when a form is visually reset.
rsx! {
form {
onreset: move |_| reset_internal_state(),
button { type: "reset", "Clear" }
}
}
Keyboard & Focus Events
onkeydown
Targets: inputtextareaglobal
Fires when a physical key is depressed.
rsx! {
input {
onkeydown: move |event| {
if event.key() == Key::Enter { submit() }
}
}
}
onkeyup
Targets: inputglobal
Fires when a key is released.
rsx! {
input { onkeyup: move |event| log::info!("Key released: {:?}", event.key()) }
}
onkeypress
Targets: input
Deprecated in modern web, but supported for legacy character-producing keys.
rsx! {
input { onkeypress: move |event| check_char(event) }
}
onfocus
Targets: inputbuttona
Fires when an element receives focus. Does not bubble.
rsx! {
input { onfocus: move |_| is_focused.set(true) }
}
onblur
Targets: inputbutton
Fires when an element loses focus.
rsx! {
input { onblur: move |_| is_focused.set(false) }
}
onfocusin
Targets: divform
The bubbling equivalent of onfocus. Captures child focus events.
rsx! {
form { onfocusin: move |_| highlight_form(true) }
}
onfocusout
Targets: divform
The bubbling equivalent of onblur.
rsx! {
form { onfocusout: move |_| highlight_form(false) }
}
Mouse Events
onclick
Targets: buttonadiv
rsx! {
button { onclick: move |_| count += 1, "Click Me" }
}
oncontextmenu
Targets: global
Fires on right-click before native menus open. Use prevent_default() to render custom menus.
rsx! {
div {
oncontextmenu: move |event| {
event.prevent_default();
open_custom_menu(event.client_coordinates());
}
}
}
ondoubleclick / ondblclick
Targets: global
rsx! {
div { ondoubleclick: move |_| like_post() }
}
onmousedown / onmouseup
Targets: global
rsx! {
canvas {
onmousedown: move |_| start_drawing(),
onmouseup: move |_| stop_drawing()
}
}
onmouseenter / onmouseleave
Targets: global
Non-bubbling hover events.
rsx! {
div {
onmouseenter: move |_| is_hovered.set(true),
onmouseleave: move |_| is_hovered.set(false)
}
}
onmouseover / onmouseout
Targets: global
Bubbling hover events.
rsx! {
ul { onmouseover: move |event| handle_child_hover(event) }
}
onmousemove
Targets: global
rsx! {
div { onmousemove: move |event| track_cursor(event.client_coordinates()) }
}
onauxclick
Targets: global
Captures non-primary mouse buttons (like middle click).
rsx! {
a { onauxclick: move |event| open_in_bg_tab() }
}
Pointer & Touch Events
Unifies mouse, touch, and pen interactions into single handlers.
onpointerdown / onpointerup / onpointermove
Targets: global
rsx! {
canvas {
onpointerdown: move |e| handle_contact(e),
onpointermove: move |e| draw_stroke(e),
onpointerup: move |e| end_contact(e)
}
}
onpointerenter / onpointerleave / onpointerover / onpointerout
Targets: global
rsx! {
div { onpointerenter: move |_| show_tooltip() }
}
onpointercancel
Targets: global
Fires when the OS interrupts the pointer (e.g., orientation change).
rsx! {
div { onpointercancel: move |_| reset_state_machine() }
}
ongotpointercapture / onlostpointercapture
Targets: global
rsx! {
div { onlostpointercapture: move |_| cleanup_capture() }
}
ontouchstart / ontouchmove / ontouchend / ontouchcancel
Targets: global
rsx! {
div {
ontouchstart: move |e| calculate_pinch_zoom(e)
}
}
Drag & Drop Events
ondragstart / ondrag / ondragend
Targets: Draggable elements
rsx! {
div {
draggable: "true",
ondragstart: move |event| event.data_transfer().set_data("text", "item_id"),
ondrag: move |_| update_ghost_position(),
ondragend: move |_| cleanup_drag()
}
}
ondragenter / ondragover / ondragleave / ondragexit / ondrop
Targets: Drop zones
rsx! {
div {
ondragenter: move |_| highlight_zone(true),
ondragleave: move |_| highlight_zone(false),
ondragover: move |event| event.prevent_default(), // MUST DO THIS TO ALLOW DROP
ondrop: move |event| process_files(event.data_transfer().files()),
ondragexit: move |_| finalize_exit()
}
}
Media Lifecycle Events
onloadstart / onprogress / onloadedmetadata / onloadeddata
Targets: videoaudio
Network fetching and parsing lifecycle.
rsx! {
video {
onloadstart: move |_| show_spinner(),
onloadedmetadata: move |e| set_duration(e.duration()),
onloadeddata: move |_| hide_spinner(),
onprogress: move |_| update_buffer_bar()
}
}
oncanplay / oncanplaythrough / onwaiting / onsuspend / onstalled
Targets: videoaudio
rsx! {
video {
oncanplay: move |_| enable_play_button(),
oncanplaythrough: move |_| auto_play(),
onwaiting: move |_| show_buffering(),
onstalled: move |_| handle_network_error(),
onsuspend: move |_| check_buffer_full()
}
}
onplay / onplaying / onpause / onended
Targets: videoaudio
rsx! {
video {
onplay: move |_| set_status("Requested Play"),
onplaying: move |_| set_status("Currently Rendering"),
onpause: move |_| set_status("Paused"),
onended: move |_| play_next_in_queue()
}
}
ontimeupdate / ondurationchange / onvolumechange
Targets: videoaudio
rsx! {
video {
ontimeupdate: move |e| update_scrubber(e.current_time()),
ondurationchange: move |e| max_time.set(e.duration()),
onvolumechange: move |e| sync_mute_icon(e.volume())
}
}
onseeking / onseeked / onratechange
Targets: videoaudio
rsx! {
video {
onseeking: move |_| pause_sync(),
onseeked: move |_| resume_sync(),
onratechange: move |e| update_speed_ui(e.playback_rate())
}
}
onemptied / onencrypted
Targets: videoaudio
rsx! {
video {
onemptied: move |_| handle_fatal_error(),
onencrypted: move |_| initialize_drm_workflow()
}
}
Layout & Scroll Events
onscroll / onscrollend / onwheel
Targets: globaloverflow-containers
rsx! {
div {
onscroll: move |_| update_parallax(),
onscrollend: move |_| snap_to_grid(),
onwheel: move |e| map_zoom(e.delta_y())
}
}
onresize
Targets: global
rsx! {
div { onresize: move |e| recalculate_canvas(e.rect()) }
}
Clipboard & Selection Events
oncopy / oncut / onpaste
Targets: inputtextareacontenteditable
rsx! {
div {
contenteditable: "true",
oncopy: move |_| append_attribution(),
oncut: move |_| handle_cut(),
onpaste: move |e| strip_rich_formatting(e)
}
}
onselect / onselectstart / onselectionchange
Targets: inputglobal
rsx! {
input {
onselect: move |_| show_formatting_tooltip(),
onselectstart: move |_| begin_tracking(),
onselectionchange: move |_| update_highlight()
}
}
oncompositionstart / oncompositionupdate / oncompositionend
Targets: input
Crucial for IME (Input Method Editor) interactions like typing CJK characters.
rsx! {
input {
oncompositionstart: move |_| disable_validation(),
oncompositionupdate: move |e| show_preview(e.data()),
oncompositionend: move |e| commit_text(e.data())
}
}
Animations & Transitions
onanimationstart / onanimationiteration / onanimationend
Targets: global
rsx! {
div {
class: "animate-pulse",
onanimationstart: move |_| init_logic(),
onanimationiteration: move |_| tick_counter(),
onanimationend: move |_| remove_element()
}
}
ontransitionend
Targets: global
rsx! {
div { ontransitionend: move |e| finalize_fade_out() }
}
Widgets, Resources & Lifecycles
ontoggle / onbeforetoggle / oncancel
Targets: detailsdialog
rsx! {
dialog {
onbeforetoggle: move |_| trigger_fade_css(),
ontoggle: move |e| sync_state(e.new_state()),
oncancel: move |_| handle_esc_key()
}
}
onload / onerror / onabort
Targets: imgiframescript
rsx! {
img {
src: "profile.jpg",
onload: move |_| reveal_image(),
onerror: move |_| set_fallback_src(),
onabort: move |_| log_cancellation()
}
}
onmounted (or onmount)
Targets: global
Fires exactly once when the element physically mounts to the underlying renderer (e.g., HTML DOM). Used to access native bounding boxes, force focus, or trigger imperative scrolling.
rsx! {
div {
onmounted: move |event| async move {
if let Ok(rect) = event.get_client_rect().await {
setup_floating_ui(rect);
}
}
}
}
onvisible
Targets: global
An Intersection Observer hook that triggers when the element enters the visible viewport.
rsx! {
img {
onvisible: move |_| fetch_high_res_image(),
src: "placeholder.jpg"
}
}