Require every field in router variants to be present in the route in the web history (#2159)
* require every field to be present in the URL in the web history * remove desktop only extra field from the simple routes example
This commit is contained in:
1 parent
329c323b35
commit
e8491d5cf4
4 files changed
+42
-7
No files matched your search
@@ -22,3 +22,4 @@ slab = { workspace = true }
|
|||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
web = []
|
||||||
@@ -62,7 +62,6 @@ mod segment;
|
|||||||
/// user_id: usize,
|
/// user_id: usize,
|
||||||
/// dynamic: usize,
|
/// dynamic: usize,
|
||||||
/// query: String,
|
/// query: String,
|
||||||
/// extra: String,
|
|
||||||
/// },
|
/// },
|
||||||
/// #[route("/hello_world")]
|
/// #[route("/hello_world")]
|
||||||
/// // You can opt out of the layout by using the `!` prefix
|
/// // You can opt out of the layout by using the `!` prefix
|
||||||
@@ -437,9 +436,47 @@ impl RouteEnum {
|
|||||||
site_map,
|
site_map,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// If we're on the web, only the URL history is preserved between navigation. We need to warn the user that the segment is not present in the URL.
|
||||||
|
if cfg!(feature = "web") {
|
||||||
|
for variant in &data.variants {
|
||||||
|
for field in &variant.fields {
|
||||||
|
if !myself.field_present_in_url(field.ident.as_ref().unwrap()) {
|
||||||
|
return Err(syn::Error::new_spanned(
|
||||||
|
field.ident.as_ref().unwrap(),
|
||||||
|
format!("The `{}` field must be present in the url for the web history. You can include the field in the url by using the `#[route(\"/:{}\")]` attribute on the enum variant.", field.ident.as_ref().unwrap(), field.ident.as_ref().unwrap()),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Ok(myself)
|
Ok(myself)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn field_present_in_url(&self, field: &Ident) -> bool {
|
||||||
|
let mut from_route = false;
|
||||||
|
|
||||||
|
for nest in &self.nests {
|
||||||
|
if nest.dynamic_segments_names().any(|i| &i == field) {
|
||||||
|
from_route = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for route in &self.routes {
|
||||||
|
for segment in &route.segments {
|
||||||
|
if segment.name().as_ref() == Some(field) {
|
||||||
|
from_route = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if let Some(query) = &route.query {
|
||||||
|
if query.contains_ident(field) {
|
||||||
|
from_route = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
from_route
|
||||||
|
}
|
||||||
|
|
||||||
fn impl_display(&self) -> TokenStream2 {
|
fn impl_display(&self) -> TokenStream2 {
|
||||||
let mut display_match = Vec::new();
|
let mut display_match = Vec::new();
|
||||||
|
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ default = []
|
|||||||
ssr = ["dioxus-ssr/incremental", "tokio", "dioxus-fullstack?/server"]
|
ssr = ["dioxus-ssr/incremental", "tokio", "dioxus-fullstack?/server"]
|
||||||
liveview = ["dioxus-liveview", "tokio", "dep:serde", "serde_json"]
|
liveview = ["dioxus-liveview", "tokio", "dep:serde", "serde_json"]
|
||||||
wasm_test = []
|
wasm_test = []
|
||||||
web = ["gloo", "web-sys", "wasm-bindgen", "gloo-utils", "js-sys"]
|
web = ["gloo", "web-sys", "wasm-bindgen", "gloo-utils", "js-sys", "dioxus-router-macro/web"]
|
||||||
fullstack = ["dioxus-fullstack"]
|
fullstack = ["dioxus-fullstack"]
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
@@ -54,7 +54,6 @@ name = "incremental"
|
|||||||
required-features = ["ssr"]
|
required-features = ["ssr"]
|
||||||
harness = false
|
harness = false
|
||||||
|
|
||||||
|
|
||||||
# you need to comment this out when publishing since cargo workspaces is not smart enough to wipe this when dropping
|
# you need to comment this out when publishing since cargo workspaces is not smart enough to wipe this when dropping
|
||||||
# dev-dependncey crates
|
# dev-dependncey crates
|
||||||
[target.'cfg(target_family = "wasm")'.dev-dependencies]
|
[target.'cfg(target_family = "wasm")'.dev-dependencies]
|
||||||
|
|||||||
@@ -65,17 +65,16 @@ fn UserFrame(user_id: usize) -> Element {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[component]
|
#[component]
|
||||||
fn Route1(user_id: usize, dynamic: usize, query: String, extra: String) -> Element {
|
fn Route1(user_id: usize, dynamic: usize, query: String) -> Element {
|
||||||
rsx! {
|
rsx! {
|
||||||
pre {
|
pre {
|
||||||
"Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\tquery:{query},\n\textra:{extra}\n}}"
|
"Route1{{\n\tuser_id:{user_id},\n\tdynamic:{dynamic},\n\tquery:{query}\n}}"
|
||||||
}
|
}
|
||||||
Link {
|
Link {
|
||||||
to: Route::Route1 {
|
to: Route::Route1 {
|
||||||
user_id,
|
user_id,
|
||||||
dynamic,
|
dynamic,
|
||||||
query: String::new(),
|
query: String::new(),
|
||||||
extra: extra.clone() + ".",
|
|
||||||
},
|
},
|
||||||
"Route1 with extra+\".\""
|
"Route1 with extra+\".\""
|
||||||
}
|
}
|
||||||
@@ -191,7 +190,6 @@ enum Route {
|
|||||||
user_id: usize,
|
user_id: usize,
|
||||||
dynamic: usize,
|
dynamic: usize,
|
||||||
query: String,
|
query: String,
|
||||||
extra: String,
|
|
||||||
},
|
},
|
||||||
#[route("/hello_world")]
|
#[route("/hello_world")]
|
||||||
// You can opt out of the layout by using the `!` prefix
|
// You can opt out of the layout by using the `!` prefix
|
||||||
|
|||||||
Reference in new issue
Block a user