Skip to content
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

No way to listen to custom events exposed by custom elements #1777

Open
1 of 3 tasks
Tracked by #1666
ranile opened this issue Mar 2, 2021 · 5 comments
Open
1 of 3 tasks
Tracked by #1666

No way to listen to custom events exposed by custom elements #1777

ranile opened this issue Mar 2, 2021 · 5 comments
Labels
A-yew-macro Area: The yew-macro crate feature-request A feature request

Comments

@ranile
Copy link
Member

ranile commented Mar 2, 2021

Tracking issue for the point, "Custom events" described in #1666

Problem

Yew should allow users to listen to custom events as well and pass CustomEvent to the callback.

There should be a way to deal with names like the ones used here. It can be a function on NodeRef or special syntax in html!, not 100% sure on the API.

from #1666

Questionnaire

  • I'm interested in fixing this myself but don't know where to start
  • I would like to fix and I have a solution
  • I don't have time to fix this right now, but maybe later

I apologize it took me so long to create this issue after being requested here (#1666 (comment))

@lukechu10
Copy link
Contributor

I created a discussion to discuss potential solutions: #1779

@mc1098 mc1098 mentioned this issue Aug 18, 2021
3 tasks
@mc1098 mc1098 added the A-yew-macro Area: The yew-macro crate label Sep 20, 2021
@mc1098
Copy link
Contributor

mc1098 commented Oct 4, 2021

For a NodeRef version I first thought of something like this:

    pub fn attach_event_listener<S, E>(
        &self,
        event: S,
        callback: Callback<E>,
    ) -> Option<gloo::events::EventListener>
    where
        S: Into<std::borrow::Cow<'static, str>>,
        E: AsRef<web_sys::Event> + JsCast + 'static,
    {
        use gloo::events::*;
        let event_target: EventTarget = self.get()?.into();
        match &callback {
            Callback::Callback { passive, .. } => {
                let passive = passive.unwrap_or_default();
                let listener = EventListener::new_with_options(
                    &event_target,
                    event,
                    EventListenerOptions {
                        phase: EventListenerPhase::Bubble,
                        passive,
                    },
                    move |e| callback.emit(e.clone().unchecked_into()),
                );
                Some(listener)
            }
            Callback::CallbackOnce(_) => {
                let listener = EventListener::once(&event_target, event, move |e| {
                    callback.emit(e.clone().unchecked_into())
                });
                Some(listener)
            }
        }
    }

We'd probably avoid leaking the gloo::events::EventListener type in the actual impl but just makes this example bit easier to read :)

Then in the rendered function of a component you might do something like this:

fn rendered(&mut self, ctx: &Context<Self>) {
    match (self.node_ref.get(), self.click_listener.as_ref()) {
        (None, Some(_)) => {
            // element has not been rendered so remove old listener
            self.click_listener.take();
        }
        (Some(_), None) => {
            // element has been rendered and no event listener has been attached
            // so add one this time.
            self.click_listener = self.node_ref.attach_event_listener(
                "click",
                ctx.link().callback(|_: yew::MouseEvent| Msg::Increment),
            );
        }
        // either the element is not rendered and there is no old listener OR
        // both the element and listener are still set - with both we do nothing :)
        _ => {}
    }
}

Also #1991 even though closed I have solved the hiccup and I'm currently keeping it up to date in my fork just in case there was any interest in that :)

@mc1098 mc1098 closed this as completed Oct 4, 2021
@mc1098 mc1098 reopened this Oct 4, 2021
@mc1098
Copy link
Contributor

mc1098 commented Oct 4, 2021

Sorry for the accidental closing 😢

@dfenerski
Copy link

Is there no workaround for this issue 😢 ? newbie here

@Roba1993
Copy link

@dfenerski Check the documentation here
I think that should work. But I'm also new to Yew and would really like to see this solved in an easier way...
@hamza1311 Has anything happened here after the discussion #1779 ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-yew-macro Area: The yew-macro crate feature-request A feature request
Projects
None yet
Development

Successfully merging a pull request may close this issue.

6 participants