Skip to content

Event propagation cancellation check happens too early? #2185

@rjmac

Description

@rjmac

Problem

I think the check for event propagation cancellation happens too early. In particular, I think that

        if unsafe { BUBBLE_EVENTS } && !event.cancel_bubble() {
            let mut el = target;
            loop {
                el = match el.parent_element() {

ought to be

        if unsafe { BUBBLE_EVENTS } {
            let mut el = target;
            while !event.cancel_bubble() {
                el = match el.parent_element() {

Steps To Reproduce

Using this simple program:

use yew::prelude::*;
use gloo_console::log;

struct Demo;

pub enum Msg {
  OuterClicked(MouseEvent),
  InnerClicked(MouseEvent)
}

impl Component for Demo {
    type Properties = ();
    type Message = Msg;

    fn create(_ctx: &Context<Self>) -> Self {
        Self
    }

    fn update(&mut self, _ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            Msg::OuterClicked(_) => {
                log!("Outer clicked");
                false
            }
            Msg::InnerClicked(ev) => {
                ev.stop_propagation();
                log!("Inner clicked");
                false
            }
        }
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        html!{
            <div onclick={ctx.link().callback(Msg::OuterClicked)}>
                <div onclick={ctx.link().callback(Msg::InnerClicked)}>
                    {"Some text"}
                    <div>{"And then a nested div"}</div>
                 </div>
            </div>
        }
    }
}

fn main() {
    ::yew::start_app::<Demo>();
}
  1. Click on "Some text". Observe it logs "Inner clicked".
  2. Click on "And then a nested div". Observe it logs both "Inner clicked" and "Outer clicked".
  3. Change yew's code as described at the top.
  4. Now clicking "And then a nested div" logs only "Inner clicked".

Expected behavior
Propagation should be cancelled even if the listener is not attached to the innermost element of the DOM element to which the event was first delivered.

Environment:

  • Yew version: master
  • Rust version: 1.56.1
  • Target, if relevant: wasm32-unknown-emscripten (probably not relevant)
  • Build tool, if relevant: trunk (proably not relevant)
  • OS, if relevant: Linux (probably not relevant)
  • Browser and version, if relevant: Firefox 94.0.2

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

If you the maintainers like the fix described at the top I can turn this into a pull request. Or you can do it if you'd rather avoid a roundtrip. Alternately, if this isn't the right change and you can describe how it's wrong, I can create a PR with the right change instead.

Metadata

Metadata

Assignees

No one assigned

    Labels

    A-yewArea: The main yew cratebug

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions