@@ -4,12 +4,12 @@ title: "Events"
44
55## Introduction
66
7- Yew integrates with the [ ` web-sys ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/ ) crate and
8- uses the events from that crate. The [ table below] ( #event-types ) lists all of the ` web-sys `
9- events that are accepted in the ` html! ` macro.
7+ Yew integrates with the [ ` web-sys ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/ ) crate and
8+ uses the events from that crate. The [ table below] ( #event-types ) lists all of the ` web-sys `
9+ events that are accepted in the ` html! ` macro.
1010
11- You can still add a [ ` Callback ` ] ( ../components/callbacks.md ) for an event that is not listed in the table below,
12- see [ Manual event listener] ( #manual-event-listener ) .
11+ You can still add a [ ` Callback ` ] ( ../components/callbacks.md ) for an event that is not listed in the table
12+ below, see [ Manual event listener] ( #manual-event-listener ) .
1313
1414## Event Types
1515
@@ -27,7 +27,7 @@ use yew::{html, Callback};
2727
2828html! {
2929 <button onclick = {Callback :: from (| _ | ())}>
30- // ^^^^^^^ event listener name
30+ // ^^^^^^^ event listener name
3131 { " Click me!" }
3232 </ button >
3333};
@@ -146,8 +146,8 @@ This will **not** always be the element at which the `Callback` is placed, that
146146[ Event.currentTarget] ( https://developer.mozilla.org/en-US/docs/Web/API/Event/currentTarget )
147147:::
148148
149- In event ` Callback ` s you may want to get the target of that event. For example, the
150- ` change ` event gives no information but is used to notify that something has changed.
149+ In event ` Callback ` s you may want to get the target of that event. For example, the
150+ ` change ` event gives no information but is used to notify that something has changed.
151151
152152In Yew getting the target element in the correct type can be done in a few ways and we will go through
153153them here. Calling [ ` web_sys::Event::target ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.Event.html#method.target )
@@ -160,25 +160,25 @@ differs opposed to the problem at hand.
160160** The Problem:**
161161
162162We have an ` onchange ` ` Callback ` on my ` <input> ` element and each time it is invoked we want to send
163- an [ update] ( ../components#update ) ` Msg ` to our component.
163+ an [ update] ( ../components#update ) ` Msg ` to our component.
164164
165- Our ` Msg ` enum looks like this:
165+ Our ` Msg ` enum looks like this:
166166
167167``` rust
168168pub enum Msg {
169- InputValue (String ),
169+ InputValue (String ),
170170}
171171```
172172
173173### Using ` JsCast `
174174
175175The [ ` wasm-bindgen ` ] ( https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/index.html ) crate has
176176a useful trait; [ ` JsCast ` ] ( https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html )
177- which allows us to hop and skip our way to the type we want, as long as it implements ` JsCast ` . We can
178- do this cautiously, which involves some runtime checks and failure types like ` Option ` and ` Result ` ,
177+ which allows us to hop and skip our way to the type we want, as long as it implements ` JsCast ` . We can
178+ do this cautiously, which involves some runtime checks and failure types like ` Option ` and ` Result ` ,
179179or we can do it dangerously.
180180
181- Enough talk, more code:
181+ Enough talk, more code:
182182
183183``` toml title="Cargo.toml"
184184[dependencies ]
@@ -215,11 +215,11 @@ impl Component for Comp {
215215 // Use batch_callback so if something unexpected happens we can return
216216 // None and do nothing
217217 let on_cautious_change = link . batch_callback (| e : Event | {
218- // When events are created the target is undefined, it's only
219- // when dispatched does the target get added.
218+ // When events are created the target is undefined, it's only
219+ // when dispatched does the target get added.
220220 let target : Option <EventTarget > = e . target ();
221- // Events can bubble so this listener might catch events from child
222- // elements which are not of type HtmlInputElement
221+ // Events can bubble so this listener might catch events from child
222+ // elements which are not of type HtmlInputElement
223223 // highlight-next-line
224224 let input = target . and_then (| t | t . dyn_into :: <HtmlInputElement >(). ok ());
225225
@@ -230,8 +230,8 @@ impl Component for Comp {
230230 let target : EventTarget = e
231231 . target ()
232232 . expect (" Event should have a target when dispatched" );
233- // You must KNOW target is a HtmlInputElement, otherwise
234- // the call to value would be Undefined Behaviour (UB).
233+ // You must KNOW target is a HtmlInputElement, otherwise
234+ // the call to value would be Undefined Behaviour (UB).
235235 // highlight-next-line
236236 Msg :: InputValue (target . unchecked_into :: <HtmlInputElement >(). value ())
237237 });
@@ -241,18 +241,17 @@ impl Component for Comp {
241241 <label for = " cautious-input" >
242242 { " My cautious input:" }
243243 <input onchange = {on_cautious_change }
244- id = " cautious-input"
245- type = " text"
246- / >
244+ id = " cautious-input"
245+ type = " text"
246+ / >
247247 </ label >
248248 <label for = " dangerous-input" >
249249 { " My dangerous input:" }
250250 <input onchange = {on_dangerous_change }
251- id = " dangerous-input"
252- type = " text"
253- / >
251+ id = " dangerous-input"
252+ type = " text"
253+ / >
254254 </ label >
255-
256255 </ >
257256 }
258257 }
@@ -266,14 +265,14 @@ The methods from `JsCast` are [`dyn_into`](https://rustwasm.github.io/wasm-bindg
266265and [ ` unchecked_into ` ] ( https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/trait.JsCast.html#method.unchecked_into )
267266and you can probably see, they allowed
268267us to go from ` EventTarget ` to [ ` HtmlInputElement ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/struct.HtmlInputElement.html ) .
269- The ` dyn_into ` method is cautious because at
270- runtime it will check whether the type is actually a ` HtmlInputElement ` and if not return an
268+ The ` dyn_into ` method is cautious because at
269+ runtime it will check whether the type is actually a ` HtmlInputElement ` and if not return an
271270` Err(JsValue) ` , the [ ` JsValue ` ] ( https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/struct.JsValue.html )
272271is a catch-all type and is essentially giving you back the object to try again.
273272
274273At this point you might be thinking... when is the dangerous version ok to use? In the case above it
275274is safe<sup >1</sup > as we've set the ` Callback ` on to an element with no children so the target can
276- only be that same element.
275+ only be that same element.
277276
278277
279278_ <sup >1</sup > As safe as anything can be when JS land is involved._
@@ -287,7 +286,7 @@ _<sup>1</sup> As safe as anything can be when JS land is involved._
287286for the behaviour of ` JsCast ` but with the smaller scope of events and their targets.
288287
289288` TargetCast ` vs ` JsCast ` is purely preference, you will find that ` TargetCast ` implements something
290- similar to what you would using ` JsCast ` .
289+ similar to what you would using ` JsCast ` .
291290:::
292291
293292The ` TargetCast ` trait builds off of ` JsCast ` and is specialized towards getting typed event targets
@@ -330,8 +329,8 @@ impl Component for Comp {
330329 });
331330
332331 let on_dangerous_change = link . callback (| e : Event | {
333- // You must KNOW target is a HtmlInputElement, otherwise
334- // the call to value would be Undefined Behaviour (UB).
332+ // You must KNOW target is a HtmlInputElement, otherwise
333+ // the call to value would be Undefined Behaviour (UB).
335334 // highlight-next-line
336335 Msg :: InputValue (e . target_unchecked_into :: <HtmlInputElement >(). value ())
337336 });
@@ -341,32 +340,31 @@ impl Component for Comp {
341340 <label for = " cautious-input" >
342341 { " My cautious input:" }
343342 <input onchange = {on_cautious_change }
344- id = " cautious-input"
345- type = " text"
346- / >
343+ id = " cautious-input"
344+ type = " text"
345+ / >
347346 </ label >
348347 <label for = " dangerous-input" >
349348 { " My dangerous input:" }
350349 <input onchange = {on_dangerous_change }
351- id = " dangerous-input"
352- type = " text"
353- / >
350+ id = " dangerous-input"
351+ type = " text"
352+ / >
354353 </ label >
355-
356354 </ >
357355 }
358356 }
359357}
360358```
361359If you followed the advice above and read about ` JsCast ` , or know the trait, you can probably
362- see that ` TargetCast::target_dyn_into ` feels similar to ` JsCast::dyn_into ` but specifically
360+ see that ` TargetCast::target_dyn_into ` feels similar to ` JsCast::dyn_into ` but specifically
363361does the cast on the target of the event. ` TargetCast::target_unchecked_into ` is similar to
364362` JsCast::unchecked_into ` , and as such all the same warnings above ` JsCast ` apply to ` TargetCast ` .
365363
366364
367365### Using ` NodeRef `
368366
369- [ ` NodeRef ` ] ( ../components/refs.md ) can be used instead of querying the event given to a ` Callback ` .
367+ [ ` NodeRef ` ] ( ../components/refs.md ) can be used instead of querying the event given to a ` Callback ` .
370368
371369``` rust
372370// highlight-next-line
@@ -410,22 +408,21 @@ impl Component for Comp {
410408 { " My input:" }
411409 // highlight-next-line
412410 <input ref = {self . my_input. clone ()}
413- {onchange }
414- id = " my-input"
415- type = " text"
416- / >
411+ {onchange }
412+ id = " my-input"
413+ type = " text"
414+ / >
417415 </ label >
418-
419416 </ >
420417 }
421418 }
422419}
423420```
424421Using ` NodeRef ` , you can ignore the event and use the ` NodeRef::cast ` method to get an
425- ` Option<HtmlInputElement> ` - this is optional as calling ` cast ` before the ` NodeRef ` has been
426- set, or when the type doesn't match will return ` None ` .
422+ ` Option<HtmlInputElement> ` - this is optional as calling ` cast ` before the ` NodeRef ` has been
423+ set, or when the type doesn't match will return ` None ` .
427424
428- You might also see by using ` NodeRef ` we don't have to send the ` String ` back in the
425+ You might also see by using ` NodeRef ` we don't have to send the ` String ` back in the
429426` Msg::InputValue ` as we always have ` my_input ` in the component state - so we could do the following:
430427
431428``` rust
@@ -436,7 +433,7 @@ pub struct Comp {
436433}
437434
438435pub enum Msg {
439- // Signal the input element has changed
436+ // Signal the input element has changed
440437 // highlight-next-line
441438 InputChanged ,
442439}
@@ -477,10 +474,10 @@ impl Component for Comp {
477474 <label for = " my-input" >
478475 { " My input:" }
479476 <input ref = {self . my_input. clone ()}
480- {onchange }
481- id = " my-input"
482- type = " text"
483- / >
477+ {onchange }
478+ id = " my-input"
479+ type = " text"
480+ / >
484481 </ label >
485482 }
486483 }
@@ -497,7 +494,7 @@ You may want to listen to an event that is not supported by Yew's `html` macro,
497494
498495In order to add an event listener to one of elements manually we need the help of
499496[ ` NodeRef ` ] ( ../components/refs ) so that in the ` rendered ` method we can add a listener using the
500- [ ` web-sys ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/index.html ) and
497+ [ ` web-sys ` ] ( https://rustwasm.github.io/wasm-bindgen/api/web_sys/index.html ) and
501498[ wasm-bindgen] ( https://rustwasm.github.io/wasm-bindgen/api/wasm_bindgen/index.html ) API.
502499We do this in ` rendered ` as this is the only time we can guarantee that the element exists in
503500the browser, Yew needs some time to create them after ` view ` is called.
@@ -511,7 +508,7 @@ in order to convert to the type required.
511508
512509### Using ` Closure ` (verbose)
513510
514- Using the ` web-sys ` and ` wasm-bindgen ` API's directly for this can be a bit painful.. so brace
511+ Using the ` web-sys ` and ` wasm-bindgen ` API's directly for this can be a bit painful.. so brace
515512yourself ([ there is a more concise way thanks to ` gloo ` ] ( #using-gloo-concise ) ).
516513
517514``` rust
@@ -569,35 +566,35 @@ impl Component for Comp {
569566 // Create a Closure from a Box<dyn Fn> - this has to be 'static
570567 let listener =
571568 Closure :: <dyn Fn (Event )>:: wrap (
572- Box :: new (move | e : Event | oncustard . emit (e ))
573- );
569+ Box :: new (move | e : Event | oncustard . emit (e ))
570+ );
574571 element
575572 . add_event_listener_with_callback (
576- " custard" ,
577- listener . as_ref (). unchecked_ref ()
578- )
573+ " custard" ,
574+ listener . as_ref (). unchecked_ref ()
575+ )
579576 . unwrap ();
580577
581- // Need to save listener in the component otherwise when the
578+ // Need to save listener in the component otherwise when the
582579 // event is fired it will try and call the listener that no longer
583580 // exists in memory!
584581 self . custard_listener = Some (listener );
585582 }
586583 }
587584
588585 fn destroy (& mut self , _ : & Context <Self >) {
589- // All done with the component but need to remove
590- // the event listener before the custard_listener memory
591- // goes out of scope.
586+ // All done with the component but need to remove
587+ // the event listener before the custard_listener memory
588+ // goes out of scope.
592589 if let (Some (element ), Some (listener )) = (
593590 self . my_div. cast :: <HtmlElement >(),
594591 self . custard_listener. take (),
595592 ) {
596593 element
597594 . remove_event_listener_with_callback (
598- " custard" ,
599- listener . as_ref (). unchecked_ref ()
600- )
595+ " custard" ,
596+ listener . as_ref (). unchecked_ref ()
597+ )
601598 . unwrap ();
602599 }
603600 }
@@ -609,7 +606,8 @@ For more information on `Closures`, see
609606
610607### Using ` gloo ` (concise)
611608
612- The easier way is with ` gloo ` , more specifically [ ` gloo_events ` ] ( https://docs.rs/gloo-events/0.1.1/gloo_events/index.html ) which is an abstraction for ` web-sys ` , ` wasm-bindgen ` .
609+ The easier way is with ` gloo ` , more specifically [ ` gloo_events ` ] ( https://docs.rs/gloo-events/0.1.1/gloo_events/index.html )
610+ which is an abstraction for ` web-sys ` , ` wasm-bindgen ` .
613611
614612` gloo_events ` has the ` EventListener ` type which can be used to create and store the
615613event listener.
@@ -673,20 +671,20 @@ impl Component for Comp {
673671 let oncustard = ctx . link (). callback (| _ : Event | Msg :: Custard );
674672
675673 let listener = EventListener :: new (
676- & element ,
677- " custard" ,
678- move | e | oncustard . emit (e . clone ())
679- );
674+ & element ,
675+ " custard" ,
676+ move | e | oncustard . emit (e . clone ())
677+ );
680678
681679 self . custard_listener = Some (listener );
682680 }
683681 }
684682}
685683```
686684
687- Notice that when using an ` EventListener ` you don't need to do anything when the
685+ Notice that when using an ` EventListener ` you don't need to do anything when the
688686component is about to be destroyed as the ` EventListener ` has a ` drop ` implementation
689- which will remove the event listener from the element.
687+ which will remove the event listener from the element.
690688
691689For more information on ` EventListener ` , see the
692690[ gloo_events docs.rs] ( https://docs.rs/gloo-events/0.1.1/gloo_events/struct.EventListener.html ) .
0 commit comments