All the event types mentioned in the following table are re-exported under yew::events. Using the types from yew::events makes it easier to ensure version compatibility than if you were to manually include web-sys as a dependency in your crate because you will not end up using a version which conflicts with the version that Yew specifies.
Events
Introduction#
Yew integrates with the web-sys crate and uses the events from that crate. The table below lists all of the web-sys events that are accepted in the html! macro.
You can still add a Callback for an event that is not listed in the table below, see Manual event listener.
Event Types#
The event listener name is the expected name when adding an event Callback in the html macro:
use *;
html! ;
The event name is the listener without the "on" prefix, therefore, the onclick event listener listens for click events. See the end of this page for a full list of available event with their types.
Event bubbling#
Events dispatched by Yew follow the virtual DOM hierarchy when bubbling up to listeners. Currently, only the bubbling phase is supported for listeners. Note that the virtual DOM hierarchy is most often, but not always, identical to the actual DOM hierarchy. The distinction is important when working with portals and other more advanced techniques. The intuition for well-implemented components should be that events bubble from children to parents. In this way the hierarchy in your coded html! is the one observed by event handlers.
If you are not interested in event bubbling, you can turn it off by calling
set_event_bubbling;
before starting your app. This speeds up event handling, but some components may break from not receiving the events they expect. Use this with care!
Event delegation#
It can be surprising that event listeners are not directly registered on the element where they are rendered. Instead, events are delegated from the subtree root of the Yew app. Still, events are delivered in their native form, and no synthetic form is created. This can lead to mismatches between the event you would expect in HTML listeners and those showing up in Yew.
Event::current_targetpoints to the Yew subtree root instead of the element the listener is added on. UseNodeRefif you want access to the underlyingHtmlElement.Event::event_phaseis alwaysEvent::CAPTURING_PHASE. Internally, the event will behave as if it was in the bubbling phase, the event propagation is replayed and the event bubbles up, i.e. event listeners higher up in the virtual DOM will trigger after event listeners below them. Currently, capturing listeners is not supported by Yew. This also means that events registered by Yew will usually fire before other event listeners.
Typed event target#
In this section target (Event.target) is always referring to the element at which the event was dispatched from.
This will not always be the element at which the Callback is placed.
In event Callbacks you may want to get the target of that event. For example, the change event gives no information but is used to notify that something has changed.
In Yew getting the target element in the correct type can be done in a few ways and we will go through them here. Calling web_sys::Event::target on an event returns an optional web_sys::EventTarget type, which might not seem very useful when you want to know the value of your input element.
In all the approaches below we are going to tackle the same problem, so it is clear where the approach differs as opposed to the problem at hand.
The Problem:
We have an onchange Callback on my <input> element and each time it is invoked we want to send an update Msg to our component.
Our Msg enum looks like this:
Using JsCast#
The wasm-bindgen crate has a useful trait: JsCast, which allows us to hop and skip our way to the type we want, as long as it implements JsCast. We can do this cautiously, which involves some runtime checks and failure types like Option and Result, or we can do it dangerously.
Enough talk, more code:
[dependencies]
# need wasm-bindgen for JsCast
wasm-bindgen = "0.2"
use JsCast;
use ;
use *;
The methods from JsCast are dyn_into and unchecked_into and you can probably see, they allowed us to go from EventTarget to HtmlInputElement. The dyn_into method is cautious because at runtime it will check whether the type is actually a HtmlInputElement and if not return an Err(JsValue), the JsValue is a catch-all type and is essentially giving you back the object to try again.
At this point you might be thinking... when is the dangerous version ok to use? In the case above it is safe1 as we've set the Callback on to an element with no children so the target can only be that same element.
1 As safe as anything can be when JS land is involved.
Using TargetCast#
It is highly recommended to read Using JsCast first!
TargetCast was designed to feel very similar to JsCast - this is to allow new users to get a feel for the behaviour of JsCast but with the smaller scope of events and their targets.
TargetCast vs JsCast is purely preference, you will find that TargetCast implements something similar to what you would using JsCast.
The TargetCast trait is built on top of JsCast and is specialized towards getting typed event targets from events.
TargetCast comes with Yew so no need to add a dependency in order to use the trait methods on events but it works in a very similar way to JsCast.
use HtmlInputElement;
use *;
If you followed the advice above and read about JsCast, you can probably see that TargetCast::target_dyn_into feels similar to JsCast::dyn_into but specifically does the cast on the target of the event. TargetCast::target_unchecked_into is similar to JsCast::unchecked_into, and as such all the same warnings above JsCast apply to TargetCast.
Using NodeRef#
NodeRef can be used instead of querying the event given to a Callback.
use HtmlInputElement;
use *;
Using NodeRef, you can ignore the event and use the NodeRef::cast method to get an Option<HtmlInputElement> - this is optional as calling cast before the NodeRef has been set, or when the type doesn't match will return None.
You might also see by using NodeRef we don't have to send the String back into state as we always have access to input_node_ref - so we could do the following:
use HtmlInputElement;
use *;
Which approach you take depends on your component and your preferences, there is no blessed way per se.
Manual event listener#
You may want to listen to an event that is not supported by Yew's html macro, see the supported events listed here.
In order to add an event listener to one of elements manually we need the help of NodeRef so that in use_effect_with we can add a listener using the web-sys and wasm-bindgen API.
The examples below are going to show adding listeners for the made-up custard event. All events either unsupported by yew or custom can be represented as a web_sys::Event. If you need to access a specific method or field on a custom / unsupported event then you can use the methods of JsCast in order to convert to the type required.
Using Closure (verbose)#
Using the web-sys and wasm-bindgen API's directly for this can be a bit painful.. so brace yourself (there is a more concise way thanks to gloo).
use ;
use HtmlElement;
use *;
For more information on Closures, see The wasm-bindgen Guide.
Using gloo (concise)#
The easier way is with gloo, more specifically gloo_events which is an abstraction for web-sys, wasm-bindgen.
gloo_events has the EventListener type which can be used to create and store the event listener.
[dependencies]
gloo-events = "0.1"
use HtmlElement;
use *;
use EventListener;
For more information on EventListener, see the gloo_events docs.rs.
Full list of available events#
| Event listener name | web_sys Event Type |
|---|---|
onabort | Event |
onauxclick | MouseEvent |
onblur | FocusEvent |
oncancel | Event |
oncanplay | Event |
oncanplaythrough | Event |
onchange | Event |
onclick | MouseEvent |
onclose | Event |
oncontextmenu | MouseEvent |
oncuechange | Event |
ondblclick | MouseEvent |
ondrag | DragEvent |
ondragend | DragEvent |
ondragenter | DragEvent |
ondragexit | DragEvent |
ondragleave | DragEvent |
ondragover | DragEvent |
ondragstart | DragEvent |
ondrop | DragEvent |
ondurationchange | Event |
onemptied | Event |
onended | Event |
onerror | Event |
onfocus | FocusEvent |
onfocusin | FocusEvent |
onfocusout | FocusEvent |
onformdata | Event |
oninput | InputEvent |
oninvalid | Event |
onkeydown | KeyboardEvent |
onkeypress | KeyboardEvent |
onkeyup | KeyboardEvent |
onload | Event |
onloadeddata | Event |
onloadedmetadata | Event |
onloadstart | ProgressEvent |
onmousedown | MouseEvent |
onmouseenter | MouseEvent |
onmouseleave | MouseEvent |
onmousemove | MouseEvent |
onmouseout | MouseEvent |
onmouseover | MouseEvent |
onmouseup | MouseEvent |
onpause | Event |
onplay | Event |
onplaying | Event |
onprogress | ProgressEvent |
onratechange | Event |
onreset | Event |
onresize | Event |
onscroll | Event |
onsecuritypolicyviolation | Event |
onseeked | Event |
onseeking | Event |
onselect | Event |
onslotchange | Event |
onstalled | Event |
onsubmit | SubmitEvent |
onsuspend | Event |
ontimeupdate | Event |
ontoggle | Event |
onvolumechange | Event |
onwaiting | Event |
onwheel | WheelEvent |
oncopy | Event |
oncut | Event |
onpaste | Event |
onanimationcancel | AnimationEvent |
onanimationend | AnimationEvent |
onanimationiteration | AnimationEvent |
onanimationstart | AnimationEvent |
ongotpointercapture | PointerEvent |
onloadend | ProgressEvent |
onlostpointercapture | PointerEvent |
onpointercancel | PointerEvent |
onpointerdown | PointerEvent |
onpointerenter | PointerEvent |
onpointerleave | PointerEvent |
onpointerlockchange | Event |
onpointerlockerror | Event |
onpointermove | PointerEvent |
onpointerout | PointerEvent |
onpointerover | PointerEvent |
onpointerup | PointerEvent |
onselectionchange | Event |
onselectstart | Event |
onshow | Event |
ontouchcancel | TouchEvent |
ontouchend | TouchEvent |
ontouchmove | TouchEvent |
ontouchstart | TouchEvent |
ontransitioncancel | TransitionEvent |
ontransitionend | TransitionEvent |
ontransitionrun | TransitionEvent |
ontransitionstart | TransitionEvent |