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

Allow customizing basis of route detection #1977

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion packages/yew-router/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

use crate::Routable;
use gloo::events::EventListener;
use std::collections::BTreeMap;
use std::rc::Rc;
use yew::prelude::*;

Expand Down Expand Up @@ -36,12 +37,16 @@ impl<T> PartialEq for RenderFn<T> {
pub struct RouterProps<R> {
/// Callback which returns [`Html`] to be rendered for the current route.
pub render: RenderFn<R>,
/// The basis from which the route is determined.
#[prop_or_default]
pub basis: RouteBasis,
}

impl<R> Clone for RouterProps<R> {
fn clone(&self) -> Self {
Self {
render: self.render.clone(),
basis: self.basis.clone(),
}
}
}
Expand All @@ -57,6 +62,42 @@ pub enum Msg {
ReRender,
}

/// The basis from which the route is determined.
#[derive(Debug, Clone)]
pub enum RouteBasis {
/// The path of the URL.
Pathname,
/// A search parameter of the URL.
Query(String),
/// The hash component of the URL.
Hash,
}

impl RouteBasis {
/// Resolves the route from the environment.
pub fn resolve(&self) -> String {
match self {
Self::Pathname => yew::utils::window().location().pathname().unwrap(),
Self::Query(which) => {
let query = yew::utils::window().location().search().unwrap();
let map: BTreeMap<String, String> =
match serde_urlencoded::from_str(query.strip_prefix('?').unwrap_or("")) {
Ok(map) => map,
Err(_) => return String::new(),
};
map.get(which).map_or_else(String::new, String::clone)
}
Self::Hash => yew::utils::window().location().hash().unwrap(),
}
}
}

impl Default for RouteBasis {
fn default() -> Self {
Self::Pathname
}
}

/// The router component.
///
/// When a route can't be matched, it looks for the route with `not_found` attribute.
Expand Down Expand Up @@ -100,7 +141,7 @@ where
}

fn view(&self) -> Html {
let pathname = yew::utils::window().location().pathname().unwrap();
let pathname = self.props.basis.resolve();
let route = R::recognize(&pathname);

match route {
Expand Down