From ba551fda0136c76a11b2248ec74c34491768fe4a Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Tue, 8 May 2018 20:46:21 +0200 Subject: [PATCH] fix(router): dynamic redirects --- core/src/components.d.ts | 1 + core/src/components/router/readme.md | 3 ++ core/src/components/router/router.tsx | 65 ++++++++++------------- core/src/components/router/utils/debug.ts | 14 ++++- 4 files changed, 44 insertions(+), 39 deletions(-) diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 9198afff58..f9d2db1251 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -5114,6 +5114,7 @@ declare global { namespace StencilComponents { interface IonRouter { 'navChanged': (direction: RouterDirection) => Promise; + 'printDebug': () => void; 'push': (url: string, direction?: RouterDirection) => Promise; /** * By default `ion-router` will match the routes at the root path ("/"). That can be changed when T diff --git a/core/src/components/router/readme.md b/core/src/components/router/readme.md index c1a102e247..a480c5f519 100644 --- a/core/src/components/router/readme.md +++ b/core/src/components/router/readme.md @@ -150,6 +150,9 @@ By default, this property is `true`, change to `false` to allow hash-less URLs. #### navChanged() +#### printDebug() + + #### push() diff --git a/core/src/components/router/router.tsx b/core/src/components/router/router.tsx index fd84831faf..98ff156742 100644 --- a/core/src/components/router/router.tsx +++ b/core/src/components/router/router.tsx @@ -1,11 +1,14 @@ import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core'; import { Config, QueueController } from '../../interface'; +import { debounce } from '../../utils/helpers'; +import { printRedirects, printRoutes } from './utils/debug'; import { readNavState, waitUntilNavNode, writeNavState } from './utils/dom'; import { RouteChain, RouteRedirect, RouterDirection, RouterEventDetail } from './utils/interface'; import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching'; import { flattenRouterTree, readRedirects, readRoutes } from './utils/parser'; import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path'; + @Component({ tag: 'ion-router' }) @@ -15,10 +18,8 @@ export class Router { private previousPath: string|null = null; private redirects: RouteRedirect[] = []; private busy = false; - private init = false; private state = 0; private lastState = 0; - private timer: any; @Element() el!: HTMLElement; @@ -62,47 +63,15 @@ export class Router { this.routes = flattenRouterTree(tree); this.redirects = readRedirects(this.el); + this.win.addEventListener('ionRouteRedirectChanged', debounce(this.onRedirectChanged.bind(this), 10)); + this.win.addEventListener('ionRouteDataChanged', debounce(this.onRoutesChanged.bind(this), 100)); + const changed = await this.writeNavStateRoot(this.getPath(), RouterDirection.None); if (!changed) { console.error('[ion-router] did not change on will load'); } } - componentDidLoad() { - this.init = true; - console.debug('[ion-router] router did load'); - } - - @Listen('ionRouteRedirectChanged') - protected onRedirectChanged(ev: CustomEvent) { - if (!this.init) { - return; - } - console.debug('[ion-router] redirect data changed', ev.target); - this.redirects = readRedirects(this.el); - } - - @Listen('ionRouteDataChanged') - protected onRoutesChanged(ev: CustomEvent) { - if (!this.init) { - return; - } - console.debug('[ion-router] route data changed', ev.target, ev.detail); - - // schedule write - if (this.timer) { - clearTimeout(this.timer); - this.timer = undefined; - } - this.timer = setTimeout(() => { - console.debug('[ion-router] data changed -> update nav'); - const tree = readRoutes(this.el); - this.routes = flattenRouterTree(tree); - this.writeNavStateRoot(this.getPath(), RouterDirection.None); - this.timer = undefined; - }, 100); - } - @Listen('window:popstate') protected onPopState() { const direction = this.historyDirection(); @@ -111,6 +80,20 @@ export class Router { return this.writeNavStateRoot(path, direction); } + private onRedirectChanged() { + this.redirects = readRedirects(this.el); + const path = this.getPath(); + if (path && routeRedirect(path, this.redirects)) { + this.writeNavStateRoot(path, RouterDirection.None); + } + } + + private onRoutesChanged() { + const tree = readRoutes(this.el); + this.routes = flattenRouterTree(tree); + this.writeNavStateRoot(this.getPath(), RouterDirection.None); + } + private historyDirection() { if (this.win.history.state === null) { this.state++; @@ -130,6 +113,14 @@ export class Router { } } + @Method() + printDebug() { + console.debug('CURRENT PATH', this.getPath()); + console.debug('PREVIOUS PATH', this.previousPath); + printRoutes(this.routes); + printRedirects(this.redirects); + } + @Method() async navChanged(direction: RouterDirection): Promise { if (this.busy) { diff --git a/core/src/components/router/utils/debug.ts b/core/src/components/router/utils/debug.ts index 04d6f97d10..478702f00c 100644 --- a/core/src/components/router/utils/debug.ts +++ b/core/src/components/router/utils/debug.ts @@ -1,8 +1,8 @@ -import { RouteChain } from './interface'; +import { RouteChain, RouteRedirect } from './interface'; import { generatePath } from './path'; export function printRoutes(routes: RouteChain[]) { - console.groupCollapsed(`[ion-core] registered ${routes.length} routes`); + console.group(`[ion-core] ROUTES[${routes.length}]`); for (const chain of routes) { const path: string[] = []; chain.forEach(r => path.push(...r.path)); @@ -11,3 +11,13 @@ export function printRoutes(routes: RouteChain[]) { } console.groupEnd(); } + +export function printRedirects(redirects: RouteRedirect[]) { + console.group(`[ion-core] REDIRECTS[${redirects.length}]`); + for (const redirect of redirects) { + if (redirect.to) { + console.debug('FROM: ', `$c ${generatePath(redirect.from)}`, 'font-weight: bold', ' TO: ', `$c ${generatePath(redirect.to)}`, 'font-weight: bold'); + } + } + console.groupEnd(); +}