Skip to content

Commit

Permalink
fix(router): fixes navChanged()
Browse files Browse the repository at this point in the history
  • Loading branch information
manucorporat committed Mar 26, 2018
1 parent 076b7e5 commit dddaee1
Show file tree
Hide file tree
Showing 17 changed files with 120 additions and 111 deletions.
10 changes: 5 additions & 5 deletions core/src/components.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ import {
} from './components/nav/view-controller';
import {
RouteID,
RouterDirection,
RouterEventDetail,
RouteWrite,
} from './components/router/utils/interfaces';
Expand Down Expand Up @@ -3502,7 +3503,6 @@ declare global {
'canGoBack': (view?: ViewController) => boolean;
'delegate': FrameworkDelegate;
'getActive': () => ViewController;
'getAllChildNavs': () => any[];
'getByIndex': (index: number) => ViewController;
'getPrevious': (view?: ViewController) => ViewController;
'getRouteId': () => RouteID;
Expand Down Expand Up @@ -3546,7 +3546,7 @@ declare global {
export interface IonNavAttributes extends HTMLAttributes {
'animated'?: boolean;
'delegate'?: FrameworkDelegate;
'onIonNavChanged'?: (event: CustomEvent) => void;
'onIonNavChanged'?: (event: CustomEvent<void>) => void;
'root'?: any;
'rootParams'?: any;
'swipeBackEnabled'?: boolean;
Expand Down Expand Up @@ -4733,8 +4733,8 @@ declare global {
declare global {
interface HTMLIonRouterElement extends HTMLStencilElement {
'base': string;
'navChanged': (isPop: boolean) => Promise<boolean>;
'push': (url: string, backDirection?: boolean) => Promise<boolean>;
'navChanged': (direction: RouterDirection) => Promise<boolean>;
'push': (url: string, direction?: RouterDirection) => Promise<boolean>;
'useHash': boolean;
}
var HTMLIonRouterElement: {
Expand Down Expand Up @@ -5977,7 +5977,7 @@ declare global {
* Emitted when the tab changes.
*/
'onIonChange'?: (event: CustomEvent) => void;
'onIonNavChanged'?: (event: CustomEvent<any>) => void;
'onIonNavChanged'?: (event: CustomEvent<void>) => void;
'scrollable'?: boolean;
/**
* If true, the tabbar
Expand Down
3 changes: 2 additions & 1 deletion core/src/components/back-button/back-button.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { Component, Element, Prop } from '@stencil/core';
import { Config } from '../../index';
import { openURL } from '../../utils/theme';
import { RouterDirection } from '../router/utils/interfaces';

@Component({
tag: 'ion-back-button',
Expand Down Expand Up @@ -41,7 +42,7 @@ export class BackButton {
ev.preventDefault();
nav.pop();
} else if (this.defaultHref) {
openURL(this.defaultHref, ev, true);
openURL(this.defaultHref, ev, RouterDirection.Back);
}
}

Expand Down
4 changes: 0 additions & 4 deletions core/src/components/hide-when/hide-when.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,4 @@ export class HideWhen implements DisplayWhen {
}
};
}

}



5 changes: 3 additions & 2 deletions core/src/components/nav/nav-util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@ export const enum ViewState {
}

export const enum NavDirection {
back = 'back',
forward = 'forward'
Back = 'back',
Forward = 'forward'
}

export type NavParams = {[key: string]: any};
Expand All @@ -58,6 +58,7 @@ export interface NavOptions {
keyboardClose?: boolean;
progressAnimation?: boolean;
ev?: any;
updateURL?: boolean;
delegate?: FrameworkDelegate;
viewIsReady?: () => Promise<any>;
}
Expand Down
56 changes: 29 additions & 27 deletions core/src/components/nav/nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {

import { ViewController, isViewController } from './view-controller';
import { Animation, Config, DomController, FrameworkDelegate, GestureDetail, NavOutlet } from '../..';
import { RouteID, RouteWrite } from '../router/utils/interfaces';
import { RouteID, RouteWrite, RouterDirection } from '../router/utils/interfaces';
import { AnimationOptions, ViewLifecycle, lifecycle, transition } from '../../utils/transition';
import { assert } from '../../utils/helpers';

Expand All @@ -25,7 +25,6 @@ import mdTransitionAnimation from './animations/md.transition';
})
export class NavControllerBase implements NavOutlet {

private _children: NavControllerBase[] = [];
private _ids = -1;
private _init = false;
private _queue: TransitionInstruction[] = [];
Expand Down Expand Up @@ -64,7 +63,7 @@ export class NavControllerBase implements NavOutlet {
}
}

@Event() ionNavChanged: EventEmitter;
@Event() ionNavChanged: EventEmitter<void>;

componentWillLoad() {
this.id = 'n' + (++ctrlIds);
Expand Down Expand Up @@ -209,27 +208,31 @@ export class NavControllerBase implements NavOutlet {

let resolve: (result: RouteWrite) => void;
const promise = new Promise<RouteWrite>((r) => resolve = r);

let finish: Promise<boolean>;
const commonOpts: NavOptions = {
updateURL: false,
viewIsReady: () => {
let markVisible;
const p = new Promise(r => markVisible = r);
let mark: Function;
const p = new Promise(r => mark = r);
resolve({
changed: true,
element: this.getActive().element,
markVisible
markVisible: async () => {
mark();
await finish;
}
});
return p;
}
};
if (viewController) {
this.popTo(viewController, {...commonOpts, direction: NavDirection.back});
finish = this.popTo(viewController, {...commonOpts, direction: NavDirection.Back});
} else if (direction === 1) {
this.push(id, params, commonOpts);
finish = this.push(id, params, commonOpts);
} else if (direction === -1) {
this.setRoot(id, params, {...commonOpts, direction: NavDirection.back, animate: true});
finish = this.setRoot(id, params, {...commonOpts, direction: NavDirection.Back, animate: true});
} else {
this.setRoot(id, params, commonOpts);
finish = this.setRoot(id, params, commonOpts);
}
return promise;
}
Expand All @@ -244,11 +247,6 @@ export class NavControllerBase implements NavOutlet {
} : undefined;
}

@Method()
getAllChildNavs(): any[] {
return this._children.slice();
}

@Method()
canGoBack(view = this.getActive()): boolean {
return !!(view && this.getPrevious(view));
Expand Down Expand Up @@ -331,13 +329,6 @@ export class NavControllerBase implements NavOutlet {
}
this._init = true;

const isPop = result.direction === NavDirection.back;
if (this.useRouter) {
const router = document.querySelector('ion-router');
router && router.navChanged(isPop);
}
this.ionNavChanged.emit({isPop});

if (ti.done) {
ti.done(
result.hasCompleted,
Expand All @@ -348,6 +339,18 @@ export class NavControllerBase implements NavOutlet {
);
}
ti.resolve(result.hasCompleted);

if (ti.opts.updateURL !== false && this.useRouter) {
const router = document.querySelector('ion-router');
if (router) {
const direction = (result.direction === NavDirection.Back)
? RouterDirection.Back
: RouterDirection.Forward;

router && router.navChanged(direction);
}
}
this.ionNavChanged.emit();
}

private _failed(rejectReason: any, ti: TransitionInstruction) {
Expand Down Expand Up @@ -528,7 +531,7 @@ export class NavControllerBase implements NavOutlet {
}
}
// default the direction to "back"
opts.direction = opts.direction || NavDirection.back;
opts.direction = opts.direction || NavDirection.Back;
}

const finalBalance = this._views.length + (insertViews ? insertViews.length : 0) - (removeCount ? removeCount : 0);
Expand Down Expand Up @@ -556,7 +559,7 @@ export class NavControllerBase implements NavOutlet {

if (ti.enteringRequiresTransition) {
// default to forward if not already set
opts.direction = opts.direction || NavDirection.forward;
opts.direction = opts.direction || NavDirection.Forward;
}
}

Expand Down Expand Up @@ -757,7 +760,7 @@ export class NavControllerBase implements NavOutlet {

// default the direction to "back";
const opts: NavOptions = {
direction: NavDirection.back,
direction: NavDirection.Back,
progressAnimation: true
};

Expand Down Expand Up @@ -809,7 +812,6 @@ export class NavControllerBase implements NavOutlet {
canSwipeBack(): boolean {
return (
this.swipeBackEnabled &&
this._children.length === 0 &&
!this.isTransitioning &&
this.canGoBack()
);
Expand Down
3 changes: 0 additions & 3 deletions core/src/components/nav/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,6 @@ boolean
#### getActive()


#### getAllChildNavs()


#### getByIndex()


Expand Down
2 changes: 1 addition & 1 deletion core/src/components/router-outlet/route-outlet.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ export class RouterOutlet implements NavOutlet {
async setRouteId(id: string, data: any, direction: number): Promise<RouteWrite> {
const changed = await this.setRoot(id, data, {
duration: direction === 0 ? 0 : undefined,
direction: direction === -1 ? NavDirection.back : NavDirection.forward,
direction: direction === -1 ? NavDirection.Back : NavDirection.Forward,
});
return {
changed,
Expand Down
57 changes: 34 additions & 23 deletions core/src/components/router/router.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Build, Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Component, Element, Event, EventEmitter, Listen, Method, Prop } from '@stencil/core';
import { Config, DomController } from '../../index';
import { flattenRouterTree, readRedirects, readRoutes } from './utils/parser';
import { readNavState, writeNavState } from './utils/dom';
import { chainToPath, generatePath, parsePath, readPath, writePath } from './utils/path';
import { RouteChain, RouteRedirect, RouterEventDetail } from './utils/interfaces';
import { RouteChain, RouteRedirect, RouterDirection, RouterEventDetail } from './utils/interfaces';
import { routeRedirect, routerIDsToChain, routerPathToChain } from './utils/matching';
import { printRoutes } from './utils/debug';

Expand Down Expand Up @@ -53,9 +53,7 @@ export class Router {
const tree = readRoutes(this.el);
this.routes = flattenRouterTree(tree);

if (Build.isDev) {
printRoutes(this.routes);
}
printRoutes(this.routes);

// schedule write
if (this.timer) {
Expand All @@ -75,49 +73,60 @@ export class Router {
this.state++;
window.history.replaceState(this.state, document.title, document.location.href);
}
const direction = window.history.state >= this.state ? 1 : -1;
this.writeNavStateRoot(this.getPath(), direction);
const direction = window.history.state >= this.state
? RouterDirection.Forward
: RouterDirection.Back;

const path = this.getPath();
console.debug('[ion-router] URL changed -> update nav', path, direction);
this.writeNavStateRoot(path, direction);
}

@Method()
async navChanged(isPop: boolean): Promise<boolean> {
async navChanged(direction: RouterDirection): Promise<boolean> {
if (this.busy) {
return false;
}
console.debug('[IN] nav changed -> update URL');
const { ids, pivot } = readNavState(document.body);
const { ids, outlet } = readNavState(document.body);
const chain = routerIDsToChain(ids, this.routes);
if (!chain) {
console.warn('no matching URL for ', ids.map(i => i.id));
return false;
}

const path = chainToPath(chain);
this.setPath(path, isPop);
if (!path) {
console.warn('router could not match path because some required param is missing');
return false;
}

if (chain.length > ids.length) {
await this.writeNavState(pivot, chain.slice(ids.length), 0);
console.debug('[ion-router] nav changed -> update URL', ids, path);
this.setPath(path, direction);
if (outlet) {
console.debug('[ion-router] updating nested outlet', outlet);
await this.writeNavState(outlet, chain, RouterDirection.None, ids.length);
}
this.emitRouteChange(path, null);
return true;
}

@Method()
push(url: string, backDirection = false) {
push(url: string, direction = RouterDirection.Forward) {
const path = parsePath(url);
this.setPath(path, backDirection);
this.setPath(path, direction);

return this.writeNavStateRoot(path, backDirection ? -1 : 1);
console.debug('[ion-router] URL pushed -> updating nav', url, direction);
return this.writeNavStateRoot(path, direction);
}

private async writeNavStateRoot(path: string[], direction: number): Promise<boolean> {
private async writeNavStateRoot(path: string[], direction: RouterDirection): Promise<boolean> {
if (this.busy) {
return false;
}
const redirect = routeRedirect(path, this.redirects);
let redirectFrom: string[] = null;
if (redirect) {
this.setPath(redirect.to, true);
this.setPath(redirect.to, direction);
redirectFrom = redirect.from;
path = redirect.to;
}
Expand All @@ -129,31 +138,33 @@ export class Router {
return changed;
}

private async writeNavState(node: any, chain: RouteChain, direction: number): Promise<boolean> {
private async writeNavState(node: any, chain: RouteChain, direction: RouterDirection, index = 0): Promise<boolean> {
if (this.busy) {
return false;
}
try {
this.busy = true;
const changed = await writeNavState(node, chain, 0, direction);
const changed = await writeNavState(node, chain, direction, index);
this.busy = false;
return changed;
} catch (e) {
this.busy = false;
throw e;
console.error(e);
return false;
}
}

private setPath(path: string[], isPop: boolean) {
private setPath(path: string[], direction: RouterDirection) {
this.state++;
writePath(window.history, this.base, this.useHash, path, isPop, this.state);
writePath(window.history, this.base, this.useHash, path, direction, this.state);
}

private getPath(): string[] | null {
return readPath(window.location, this.base, this.useHash);
}

private emitRouteChange(path: string[], redirectPath: string[]|null) {
console.debug('[ion-router] route changed', path);
const from = this.previousPath;
const redirectedFrom = redirectPath ? generatePath(redirectPath) : null;
const to = generatePath(path);
Expand Down
Loading

0 comments on commit dddaee1

Please sign in to comment.