dioxus icon indicating copy to clipboard operation
dioxus copied to clipboard

`prevent_default` is not respected after bubbling events

Open DonAlonzo opened this issue 2 years ago • 5 comments

Problem

In Liveview, prevent_default on the Link component does not work:

https://github.com/DioxusLabs/dioxus/blob/d9220d4e42b86114096a639ba0b308062b6d763a/packages/router/src/components/link.rs#L248

As a result, the link treats every route, internal or external, as an external link and the page reloads upon redirect.

Steps To Reproduce

Set up a router and Links in Liveview.

Example:

render! {
        div {
            for movie in movies {
                Link {
                    key: "{movie.id}",
                    to: match movie.screening {
                        Some(screening) => Route::Screening { id: screening },
                        None => Route::Movie { id: movie.id },
                    },
                    "{movie.name}"
                }
            }
        }
    }

Expected behavior

A Link to an internal route should be treated as an internal route. The expected behavior can be simulated by commenting out this line:

https://github.com/DioxusLabs/dioxus/blob/d9220d4e42b86114096a639ba0b308062b6d763a/packages/router/src/components/link.rs#L247)

Screenshots

N/A

Environment:

  • Dioxus version: master
  • Rust version: 1.76.0-nightly
  • OS info: Arch Linux
  • App platform: Liveview

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

DonAlonzo avatar Nov 26 '23 10:11 DonAlonzo

The simple routes example in the router package appears to work correctly in liveview. Do you have the liveview feature enabled in your cargo.toml?

dioxus-router = { git = "https://github.com/DioxusLabs/dioxus", features = "liveview" }

ealmloff avatar Nov 27 '23 19:11 ealmloff

I do! I have a workspace setup, but the result should be the same:

dioxus-router = { workspace = true, features = ["liveview"] }

and in the root:

dioxus-router = { git = "https://github.com/DioxusLabs/dioxus.git", rev = "d9220d4" }

DonAlonzo avatar Nov 27 '23 20:11 DonAlonzo

I managed to find what triggered the error.

I wanted to style my links, so I went and did this:

Link {
    to: Route::Movies,
    div {
        width: "100%",
        padding: "0.5rem",
        font_size: "1rem",
        background_color: "var(--primary)",
        color: "#fff",
        border_radius: "0.75rem",
        box_shadow: "0 0.25rem 1rem var(--monochrome-20)",
        "Filmer ➤"
    }
}

Removing the inner div makes it work perfectly (losing the styling, though).

DonAlonzo avatar Nov 27 '23 20:11 DonAlonzo

Adding prevent_default: "onclick", on the div makes it work as intended.

DonAlonzo avatar Nov 27 '23 20:11 DonAlonzo

Ok, so the larger issue here is that prevent default is taken from the element that the event originated in, but not when bubbling the event. Here is a minimal example of that bug:

use dioxus::prelude::*;

fn main() {
    dioxus_desktop::launch(app);
}

fn app(cx: Scope) -> Element {
    let mut count = use_state(cx, || 0);

    cx.render(rsx! {
        a {
            href: "http://example.com",
            prevent_default: "onclick",
            div {
                "click me"
            }
        }
    })
}

ealmloff avatar Nov 28 '23 16:11 ealmloff