-
-
Notifications
You must be signed in to change notification settings - Fork 1.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add custom event support #1991
Add custom event support #1991
Conversation
Visit the preview URL for this PR (updated for commit 7dc56d9): https://yew-rs--pr1991-on-custom-event-dd4nt6dy.web.app (expires Thu, 02 Sep 2021 21:32:36 GMT) 🔥 via Firebase Hosting GitHub Action 🌎 |
849b37d
to
8ed4aad
Compare
Uses a similar syntax to Svelte `on:click`. Yew will continue to check standard global event handlers and provide the respective `web_sys` event. For custom events the handler is registered for the event after `on:` syntax, therefore `on:custard` will register a handler for `custard` events. Custom event handlers will receive the `CustomEvent` type which is a new type for `web_sys::Event` which is used to indicate that the user is specifying a custom event handler. This should help prevent some typo's as users expecting a specific type will get an error that Yew was expecting the callback to be of type `Callback<CustomEvent>` where they might have expected `Callback<MouseEvent>`. The shorthand property assignment still works but the shorthand name required is the name of the event and this has to be used in braces after the listener prefix: `on:{click}`.
Removes stringy syntax to listener syntax ie: on:"click" - custom events now have to be explicitly defined using the CustomEventHandler trait. Added custom_event attribute macro to help reduce the boiler plate - using this new approach the custom event can be defined once and used wherever required (a nice benefit over the literal string syntax!) Add example of using imported wasm_bindgen type as these implement JsCast which means that can be easily wrapped in a NewType with the custom_event macro for custom events.
`CustomEventHandler` trait has been changed to `StaticEvent` which better reflects it's purpose - to statically describe an event. `StaticEvent` can be implemented easily to the supported standard events which allows for only one `Wrapper` and `Listener` implementation to be used to support custom and standard events. Added a doc comment for the lack of `web_sys::FormDataEvent` - this doc comment for IDE users will be visible when using the type in the `html!` macro.
Change to single Wrapper & Listener impl effected output.
Use new event listener syntax
Change `CustomEventHandler` to `StaticEvent`. Updated the traits implemented by the custom_event macro. Tweaked some wording and formatting.
Implementing Deref automatically prevents users from providing a more strongly typed alternatives. This will be common when wrapping `web_sys::CustomEvent`, as a user could provide a `detail` method on the event which returns a specific type and not just a JsValue.
8ed4aad
to
7dc56d9
Compare
Why close this? |
Didn't seem to get much interest and the #1542 added Also as you suggested in the linked issue an API on |
Adds assigning listener syntax:
If / when we support adding event listeners onto
Component
s directly it will distinguishwhen an event listener is being assigned to a
Component
instead of being passed down as a prop:Add custom event support
Custom event support comes from implementing the
StaticEvent
trait:On it's own this would allow a user implement the trait with the
Event
type being the wrapped
web_sys
event.A similar pattern is used to implement the events supported by yew, but with unit based structs as we just want the raw
web_sys
event passed in.This allows us to treat supported and custom events in the same way and reduces the need for multiple on[event] modules.
This also means that if Yew wanted to provide it's own events somewhen then we could easily utilise the
custom_event
macro to make NewTypes around the rawweb_sys
events and this would work the same internally.When implementing the trait like this if a user wanted to use a function on the NewType they would
have to wrap the event type in that NewType first, which doesn't seem very ergonomic.
It is possible for a user to use
Self
as theEvent
type but then they haveto implement
JsCast
on that type, which is not trivial even when wrapping aJsCast
type.To help with the boiler plate, this PR also adds the
custom_event
attribute macro whichcan be applied to NewTypes that wrap a type that implements
JsCast
+AsRef<web_sys::Event>
, this includes anytype imported in a
wasm_bindgen
extern block that extends Event.The
custom_event
macro has one attribute which is used to define the "event name"if this name is representable in Rust then a shorthand can be used:
Shorthand
Normal
The ident defined in the attribute can then be used in the same way as other events:
Putting it all together:
When implementing the
![image](https://user-images.githubusercontent.com/43726912/129788981-a11451a3-2cb5-4988-9798-ad2048e996b4.png)
static_event_impl
macro I added optional comments and they display really well in thehtml
macro for VSCode, I've only added a comment about theformdata
event:This could be done as is with the modules but I think it's a nice touch so have added it here as I was using a new macro_rules macro anyways.
I have changed the syntax and implementation a few times over getting to this point
but I don't think it's in bad shape (hopefully ;P) and look forward to hearing what
people think :)
Typed Custom Event
I think it's worth just going over the example that triggered the linked issue and how a solution
might look with this change. It was the ability to listen to the "MDCSnackbar:closing" event and others like it on
imported web components (in the example the
mwc-snackbar
).How this example looks today:
Snackbar in material-yew
A possible solution with this PR:
This
Component
could make theSnackBarClosingEvent
and it'ssnackbarclosing
alias public andchange the onclosing property to accept this event. This approach means the event can be defined
with the
Component
and imported by the user :)Fixes #1777
Checklist
cargo make pr-flow