`prevent_default` is not respected after bubbling events
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
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" }
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" }
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).
Adding prevent_default: "onclick", on the div makes it work as intended.
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"
}
}
})
}