static: add argument support to Router and add RouteMatch

This commit is contained in:
Jens Langhammer 2020-11-26 13:58:45 +01:00
parent 1432f0648f
commit feabd38173
3 changed files with 49 additions and 17 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -24,7 +24,7 @@ export class Route {
url: RegExp;
private element?: TemplateResult;
private callback?: () => TemplateResult;
private callback?: (args: { [key: string]: string; }) => TemplateResult;
constructor(url: RegExp, element?: TemplateResult) {
this.url = url;
@ -40,9 +40,14 @@ export class Route {
return this;
}
render(): TemplateResult {
then(render: (args: { [key: string]: string; }) => TemplateResult): Route {
this.callback = render;
return this;
}
render(args: { [key: string]: string; }): TemplateResult {
if (this.callback) {
return this.callback();
return this.callback(args);
}
if (this.element) {
return this.element;
@ -51,16 +56,36 @@ export class Route {
}
}
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
export const ROUTES: Route[] = [
// Prevent infinite Shell loops
new Route(new RegExp("^/$")).redirect("/-/overview/"),
new Route(new RegExp("^/applications/$"), html`<h1>test</h1>`),
new Route(new RegExp(`^/$`)).redirect("/-/overview/"),
new Route(new RegExp(`^/applications/$`), html`<h1>test</h1>`),
new Route(new RegExp(`^/-/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
return html`<h1>test</h1>
<span>${args.slug}</span>`;
}),
];
class RouteMatch {
route: Route;
arguments?: RegExpExecArray;
fullUrl?: string;
constructor(route: Route) {
this.route = route;
}
render(): TemplateResult {
return this.route.render(this.arguments!.groups || {});
}
}
@customElement("pb-router-outlet")
export class RouterOutlet extends LitElement {
@property()
activeRoute?: Route;
current?: RouteMatch;
@property()
defaultUrl?: string;
@ -98,28 +123,35 @@ export class RouterOutlet extends LitElement {
window.location.hash = `#${activeUrl}`;
return;
}
let selectedRoute: Route | null = null;
let matchedRoute: RouteMatch | null = null;
ROUTES.forEach((route) => {
if (route.url.exec(activeUrl)) {
selectedRoute = route;
console.log(`matching ${activeUrl} against ${route.url}`);
const match = route.url.exec(activeUrl);
if (match != null) {
matchedRoute = new RouteMatch(route);
matchedRoute.arguments = match;
matchedRoute.fullUrl = activeUrl;
return;
}
});
if (!selectedRoute) {
if (!matchedRoute) {
console.log(
`passbook/router: route "${activeUrl}" not defined, defaulting to shell`
);
selectedRoute = new Route(
const route = new Route(
RegExp(""),
html`<pb-site-shell url=${activeUrl}>
<div slot="body"></div>
</pb-site-shell>`
);
matchedRoute = new RouteMatch(route);
matchedRoute.arguments = route.url.exec(activeUrl)!;
matchedRoute.fullUrl = activeUrl;
}
this.activeRoute = selectedRoute;
this.current = matchedRoute;
}
render() {
return this.activeRoute?.render();
return this.current?.render();
}
}