refactor(router): remove getContainerEl()

This commit is contained in:
Manu Mtz.-Almeida
2018-03-21 15:48:41 +01:00
parent 4693229c84
commit 17a3001af5
8 changed files with 79 additions and 97 deletions

View File

@ -11,7 +11,7 @@ const OFF_OPACITY = 0.8;
export default function iosTransitionAnimation(Animation: Animation, navEl: HTMLElement, opts: AnimationOptions): Promise<Animation> { export default function iosTransitionAnimation(Animation: Animation, navEl: HTMLElement, opts: AnimationOptions): Promise<Animation> {
const isRTL = opts.isRTL; const isRTL = document.dir === 'rtl';
const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%'; const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%';
const OFF_LEFT = isRTL ? '31%' : '-31%'; const OFF_LEFT = isRTL ? '31%' : '-31%';

View File

@ -14,11 +14,11 @@ import {
import { ViewController, isViewController } from './view-controller'; import { ViewController, isViewController } from './view-controller';
import { Animation, Config, DomController, FrameworkDelegate, GestureDetail, NavOutlet } from '../..'; import { Animation, Config, DomController, FrameworkDelegate, GestureDetail, NavOutlet } from '../..';
import { RouteID, RouteWrite } from '../router/utils/interfaces'; import { RouteID, RouteWrite } from '../router/utils/interfaces';
import { AnimationOptions, ViewLifecycle, lifecycle, transition } from '../../utils/transition';
import { assert } from '../../utils/helpers'; import { assert } from '../../utils/helpers';
import iosTransitionAnimation from './animations/ios.transition'; import iosTransitionAnimation from './animations/ios.transition';
import mdTransitionAnimation from './animations/md.transition'; import mdTransitionAnimation from './animations/md.transition';
import { AnimationOptions, ViewLifecycle, lifecycle, transition } from '../../utils/transition';
@Component({ @Component({
tag: 'ion-nav', tag: 'ion-nav',
@ -202,7 +202,7 @@ export class NavControllerBase implements NavOutlet {
setRouteId(id: string, params: any = {}, direction: number): Promise<RouteWrite> { setRouteId(id: string, params: any = {}, direction: number): Promise<RouteWrite> {
const active = this.getActive(); const active = this.getActive();
if (active && active.component === id) { if (active && active.component === id) {
return Promise.resolve({changed: false}); return Promise.resolve({changed: false, element: active.element});
} }
const viewController = this._views.find(v => v.component === id) || id; const viewController = this._views.find(v => v.component === id) || id;
@ -215,6 +215,7 @@ export class NavControllerBase implements NavOutlet {
const p = new Promise(r => markVisible = r); const p = new Promise(r => markVisible = r);
resolve({ resolve({
changed: true, changed: true,
element: this.getActive().element,
markVisible markVisible
}); });
return p; return p;
@ -238,22 +239,11 @@ export class NavControllerBase implements NavOutlet {
@Method() @Method()
getRouteId(): RouteID|undefined { getRouteId(): RouteID|undefined {
const active = this.getActive(); const active = this.getActive();
if (active) { return active ? {
return { id: active.element.tagName,
id: active.element.tagName, params: active.data,
params: active.data element: active.element
}; } : undefined;
}
return undefined;
}
@Method()
getContainerEl(): HTMLElement|undefined {
const active = this.getActive();
if (active) {
return active.element;
}
return undefined;
} }
@Method() @Method()
@ -641,7 +631,6 @@ export class NavControllerBase implements NavOutlet {
viewIsReady: opts.viewIsReady, viewIsReady: opts.viewIsReady,
showGoBack: this.canGoBack(enteringView), showGoBack: this.canGoBack(enteringView),
isRTL: document.dir === 'rtl',
progressAnimation, progressAnimation,
baseEl: this.el, baseEl: this.el,
enteringEl, enteringEl,

View File

@ -78,9 +78,6 @@ boolean
#### getByIndex() #### getByIndex()
#### getContainerEl()
#### getPrevious() #### getPrevious()

View File

@ -1,33 +1,33 @@
import { NavOutlet, NavOutletElement, RouteChain, RouteID } from './interfaces'; import { NavOutlet, NavOutletElement, RouteChain, RouteID } from './interfaces';
export function writeNavState(root: HTMLElement, chain: RouteChain|null, index: number, direction: number): Promise<boolean> { export async function writeNavState(root: HTMLElement|undefined, chain: RouteChain|null, index: number, direction: number): Promise<boolean> {
if (!chain || index >= chain.length) { // find next navigation outlet in the DOM
return Promise.resolve(direction === 0); const outlet = searchNavNode(root);
}
const route = chain[index];
const node = searchNavNode(root);
if (!node) {
return Promise.resolve(direction === 0);
}
return node.componentOnReady()
.then(() => node.setRouteId(route.id, route.params, direction))
.catch(() => ({changed: false, markVisible: undefined}))
.then(result => {
if (result.changed) {
direction = 0;
}
const nextEl = node.getContainerEl();
const promise = (nextEl)
? writeNavState(nextEl, chain, index + 1, direction)
: Promise.resolve(direction === 0);
return promise.then((c) => { // make sure we can continue interating the DOM, otherwise abort
if (result.markVisible) { if (!chain || index >= chain.length || !outlet) {
result.markVisible(); return direction === 0;
} }
return c; await outlet.componentOnReady();
});
}); const route = chain[index];
const result = await outlet.setRouteId(route.id, route.params, direction);
// if the outlet changed the page, reset navigation to neutral (no direction)
// this means nested outlets will not animate
if (result.changed) {
direction = 0;
}
// recursivelly set nested outlets
const changed = await writeNavState(result.element, chain, index + 1, direction);
// once all nested outlets are visible let's make the parent visible too,
// using markVisible prevents flickering
if (result.markVisible) {
await result.markVisible();
}
return changed;
} }
export function readNavState(root: HTMLElement) { export function readNavState(root: HTMLElement) {
@ -39,7 +39,8 @@ export function readNavState(root: HTMLElement) {
if (pivot) { if (pivot) {
const id = pivot.getRouteId(); const id = pivot.getRouteId();
if (id) { if (id) {
node = pivot.getContainerEl(); node = id.element;
id.element = undefined;
ids.push(id); ids.push(id);
} else { } else {
break; break;
@ -51,7 +52,7 @@ export function readNavState(root: HTMLElement) {
return {ids, pivot}; return {ids, pivot};
} }
const QUERY = ':not([no-router]) ion-nav,:not([no-router]) ion-tabs'; const QUERY = ':not([no-router]) ion-nav,:not([no-router]) ion-tabs, :not([no-router]) ion-router-outlet';
function searchNavNode(root: HTMLElement|undefined): NavOutletElement|null { function searchNavNode(root: HTMLElement|undefined): NavOutletElement|null {
if (!root) { if (!root) {

View File

@ -2,8 +2,6 @@
export interface NavOutlet { export interface NavOutlet {
setRouteId(id: string, data: any, direction: number): Promise<RouteWrite>; setRouteId(id: string, data: any, direction: number): Promise<RouteWrite>;
getRouteId(): RouteID|undefined; getRouteId(): RouteID|undefined;
getContainerEl(): HTMLElement | undefined;
} }
export interface RouterEventDetail { export interface RouterEventDetail {
@ -19,11 +17,13 @@ export interface RouteRedirect {
export interface RouteWrite { export interface RouteWrite {
changed: boolean; changed: boolean;
element: HTMLElement | undefined;
markVisible?: () => void|Promise<void>; markVisible?: () => void|Promise<void>;
} }
export interface RouteID { export interface RouteID {
id: string; id: string;
element: HTMLElement|undefined;
params?: any; params?: any;
} }

View File

@ -222,9 +222,6 @@ Emitted when the tab changes.
## Methods ## Methods
#### getContainerEl()
#### getRouteId() #### getRouteId()

View File

@ -78,8 +78,9 @@ export class Tabs implements NavOutlet {
this.loadConfig('tabsHighlight', true); this.loadConfig('tabsHighlight', true);
} }
componentDidLoad() { async componentDidLoad() {
return this.initTabs().then(() => this.initSelect()); await this.initTabs();
await this.initSelect();
} }
componentDidUnload() { componentDidUnload() {
@ -97,26 +98,35 @@ export class Tabs implements NavOutlet {
* @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select. * @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select.
*/ */
@Method() @Method()
select(tabOrIndex: number | HTMLIonTabElement): Promise<boolean> { async select(tabOrIndex: number | HTMLIonTabElement): Promise<boolean> {
const selectedTab = this.getTab(tabOrIndex); const selectedTab = this.getTab(tabOrIndex);
if (!this.shouldSwitch(selectedTab)) { if (!this.shouldSwitch(selectedTab)) {
return Promise.resolve(false); return false;
} }
return this.setActive(selectedTab) await this.setActive(selectedTab);
.then(() => this.notifyRouter()) await this.notifyRouter();
.then(() => this.tabSwitch()); return this.tabSwitch();
} }
@Method() @Method()
setRouteId(id: string): Promise<RouteWrite> { async setRouteId(id: string): Promise<RouteWrite> {
const selectedTab = this.getTab(id); const selectedTab = this.getTab(id);
if (!this.shouldSwitch(selectedTab)) { if (!this.shouldSwitch(selectedTab)) {
return Promise.resolve({changed: false}); return {changed: false, element: this.selectedTab};
} }
return this.setActive(selectedTab).then(() => ({
await this.setActive(selectedTab);
return {
changed: true, changed: true,
element: this.selectedTab,
markVisible: () => { this.tabSwitch(); } markVisible: () => { this.tabSwitch(); }
})); };
}
@Method()
getRouteId(): RouteID|undefined {
const id = this.selectedTab && this.selectedTab.getTabId();
return id ? {id, element: this.selectedTab} : undefined;
} }
@Method() @Method()
@ -138,17 +148,6 @@ export class Tabs implements NavOutlet {
return this.selectedTab; return this.selectedTab;
} }
@Method()
getRouteId(): RouteID|undefined {
const id = this.selectedTab && this.selectedTab.getTabId();
return id ? {id} : undefined;
}
@Method()
getContainerEl(): HTMLElement|undefined {
return this.selectedTab;
}
private initTabs() { private initTabs() {
const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab')); const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab'));
const tabPromises = tabs.map(tab => { const tabPromises = tabs.map(tab => {
@ -161,7 +160,7 @@ export class Tabs implements NavOutlet {
return Promise.all(tabPromises); return Promise.all(tabPromises);
} }
private initSelect(): Promise<void> { private async initSelect(): Promise<void> {
if (this.useRouter) { if (this.useRouter) {
if (Build.isDev) { if (Build.isDev) {
const selectedTab = this.tabs.find(t => t.selected); const selectedTab = this.tabs.find(t => t.selected);
@ -170,7 +169,7 @@ export class Tabs implements NavOutlet {
'Define routes properly the define which tab is selected'); 'Define routes properly the define which tab is selected');
} }
} }
return Promise.resolve(); return;
} }
// find pre-selected tabs // find pre-selected tabs
const selectedTab = this.tabs.find(t => t.selected) || const selectedTab = this.tabs.find(t => t.selected) ||
@ -182,14 +181,14 @@ export class Tabs implements NavOutlet {
tab.selected = false; tab.selected = false;
} }
} }
const promise = selectedTab ? selectedTab.setActive() : Promise.resolve(null); if (selectedTab) {
return promise.then(() => { await selectedTab.setActive();
this.selectedTab = selectedTab; }
if (selectedTab) { this.selectedTab = selectedTab;
selectedTab.selected = true; if (selectedTab) {
selectedTab.active = true; selectedTab.selected = true;
} selectedTab.active = true;
}); }
} }
private loadConfig(attrKey: string, fallback: any) { private loadConfig(attrKey: string, fallback: any) {

View File

@ -9,7 +9,7 @@ export async function transition(opts: AnimationOptions): Promise<Animation|void
setZIndex(enteringEl, leavingEl, opts.direction); setZIndex(enteringEl, leavingEl, opts.direction);
showPages(enteringEl, leavingEl); showPages(enteringEl, leavingEl);
showGoBack(enteringEl, opts.showGoBack); showGoBack(enteringEl, !!opts.showGoBack);
// fast path for no animation // fast path for no animation
if (!opts.animationBuilder && !opts.animation) { if (!opts.animationBuilder && !opts.animation) {
@ -173,13 +173,12 @@ export const enum ViewLifecycle {
export interface AnimationOptions { export interface AnimationOptions {
animationCtrl: HTMLIonAnimationControllerElement; animationCtrl: HTMLIonAnimationControllerElement;
animationBuilder: AnimationBuilder; animationBuilder: AnimationBuilder;
animation: Animation|undefined; animation?: Animation;
direction: NavDirection; direction?: NavDirection;
duration: number|undefined; duration?: number;
easing: string|undefined; easing?: string;
isRTL: boolean; viewIsReady?: () => Promise<any>;
showGoBack: boolean; showGoBack?: boolean;
viewIsReady: undefined | (() => Promise<any>);
progressAnimation?: Function; progressAnimation?: Function;
enteringEl: HTMLElement; enteringEl: HTMLElement;
leavingEl: HTMLElement; leavingEl: HTMLElement;