diff --git a/core/src/components/nav/animations/ios.transition.ts b/core/src/components/nav/animations/ios.transition.ts index 297724940c..320ae60205 100644 --- a/core/src/components/nav/animations/ios.transition.ts +++ b/core/src/components/nav/animations/ios.transition.ts @@ -11,7 +11,7 @@ const OFF_OPACITY = 0.8; export default function iosTransitionAnimation(Animation: Animation, navEl: HTMLElement, opts: AnimationOptions): Promise { - const isRTL = opts.isRTL; + const isRTL = document.dir === 'rtl'; const OFF_RIGHT = isRTL ? '-99.5%' : '99.5%'; const OFF_LEFT = isRTL ? '31%' : '-31%'; diff --git a/core/src/components/nav/nav.tsx b/core/src/components/nav/nav.tsx index 215b813305..dae4bec3ca 100644 --- a/core/src/components/nav/nav.tsx +++ b/core/src/components/nav/nav.tsx @@ -14,11 +14,11 @@ import { import { ViewController, isViewController } from './view-controller'; import { Animation, Config, DomController, FrameworkDelegate, GestureDetail, NavOutlet } from '../..'; import { RouteID, RouteWrite } from '../router/utils/interfaces'; +import { AnimationOptions, ViewLifecycle, lifecycle, transition } from '../../utils/transition'; import { assert } from '../../utils/helpers'; import iosTransitionAnimation from './animations/ios.transition'; import mdTransitionAnimation from './animations/md.transition'; -import { AnimationOptions, ViewLifecycle, lifecycle, transition } from '../../utils/transition'; @Component({ tag: 'ion-nav', @@ -202,7 +202,7 @@ export class NavControllerBase implements NavOutlet { setRouteId(id: string, params: any = {}, direction: number): Promise { const active = this.getActive(); 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; @@ -215,6 +215,7 @@ export class NavControllerBase implements NavOutlet { const p = new Promise(r => markVisible = r); resolve({ changed: true, + element: this.getActive().element, markVisible }); return p; @@ -238,22 +239,11 @@ export class NavControllerBase implements NavOutlet { @Method() getRouteId(): RouteID|undefined { const active = this.getActive(); - if (active) { - return { - id: active.element.tagName, - params: active.data - }; - } - return undefined; - } - - @Method() - getContainerEl(): HTMLElement|undefined { - const active = this.getActive(); - if (active) { - return active.element; - } - return undefined; + return active ? { + id: active.element.tagName, + params: active.data, + element: active.element + } : undefined; } @Method() @@ -641,7 +631,6 @@ export class NavControllerBase implements NavOutlet { viewIsReady: opts.viewIsReady, showGoBack: this.canGoBack(enteringView), - isRTL: document.dir === 'rtl', progressAnimation, baseEl: this.el, enteringEl, diff --git a/core/src/components/nav/readme.md b/core/src/components/nav/readme.md index b90140b759..dbc835aea2 100644 --- a/core/src/components/nav/readme.md +++ b/core/src/components/nav/readme.md @@ -78,9 +78,6 @@ boolean #### getByIndex() -#### getContainerEl() - - #### getPrevious() diff --git a/core/src/components/router/utils/dom.ts b/core/src/components/router/utils/dom.ts index efd8a4e4ba..cae1d9e16e 100644 --- a/core/src/components/router/utils/dom.ts +++ b/core/src/components/router/utils/dom.ts @@ -1,33 +1,33 @@ import { NavOutlet, NavOutletElement, RouteChain, RouteID } from './interfaces'; -export function writeNavState(root: HTMLElement, chain: RouteChain|null, index: number, direction: number): Promise { - if (!chain || index >= chain.length) { - return Promise.resolve(direction === 0); - } - 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); +export async function writeNavState(root: HTMLElement|undefined, chain: RouteChain|null, index: number, direction: number): Promise { + // find next navigation outlet in the DOM + const outlet = searchNavNode(root); - return promise.then((c) => { - if (result.markVisible) { - result.markVisible(); - } - return c; - }); - }); + // make sure we can continue interating the DOM, otherwise abort + if (!chain || index >= chain.length || !outlet) { + return direction === 0; + } + 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) { @@ -39,7 +39,8 @@ export function readNavState(root: HTMLElement) { if (pivot) { const id = pivot.getRouteId(); if (id) { - node = pivot.getContainerEl(); + node = id.element; + id.element = undefined; ids.push(id); } else { break; @@ -51,7 +52,7 @@ export function readNavState(root: HTMLElement) { 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 { if (!root) { diff --git a/core/src/components/router/utils/interfaces.ts b/core/src/components/router/utils/interfaces.ts index 28594ccece..75a17f8dc6 100644 --- a/core/src/components/router/utils/interfaces.ts +++ b/core/src/components/router/utils/interfaces.ts @@ -2,8 +2,6 @@ export interface NavOutlet { setRouteId(id: string, data: any, direction: number): Promise; getRouteId(): RouteID|undefined; - - getContainerEl(): HTMLElement | undefined; } export interface RouterEventDetail { @@ -19,11 +17,13 @@ export interface RouteRedirect { export interface RouteWrite { changed: boolean; + element: HTMLElement | undefined; markVisible?: () => void|Promise; } export interface RouteID { id: string; + element: HTMLElement|undefined; params?: any; } diff --git a/core/src/components/tabs/readme.md b/core/src/components/tabs/readme.md index 5a2e1d3eb6..d1729cc434 100644 --- a/core/src/components/tabs/readme.md +++ b/core/src/components/tabs/readme.md @@ -222,9 +222,6 @@ Emitted when the tab changes. ## Methods -#### getContainerEl() - - #### getRouteId() diff --git a/core/src/components/tabs/tabs.tsx b/core/src/components/tabs/tabs.tsx index c251557ead..1f8f7ff279 100644 --- a/core/src/components/tabs/tabs.tsx +++ b/core/src/components/tabs/tabs.tsx @@ -78,8 +78,9 @@ export class Tabs implements NavOutlet { this.loadConfig('tabsHighlight', true); } - componentDidLoad() { - return this.initTabs().then(() => this.initSelect()); + async componentDidLoad() { + await this.initTabs(); + await this.initSelect(); } componentDidUnload() { @@ -97,26 +98,35 @@ export class Tabs implements NavOutlet { * @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select. */ @Method() - select(tabOrIndex: number | HTMLIonTabElement): Promise { + async select(tabOrIndex: number | HTMLIonTabElement): Promise { const selectedTab = this.getTab(tabOrIndex); if (!this.shouldSwitch(selectedTab)) { - return Promise.resolve(false); + return false; } - return this.setActive(selectedTab) - .then(() => this.notifyRouter()) - .then(() => this.tabSwitch()); + await this.setActive(selectedTab); + await this.notifyRouter(); + return this.tabSwitch(); } @Method() - setRouteId(id: string): Promise { + async setRouteId(id: string): Promise { const selectedTab = this.getTab(id); 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, + element: this.selectedTab, markVisible: () => { this.tabSwitch(); } - })); + }; + } + + @Method() + getRouteId(): RouteID|undefined { + const id = this.selectedTab && this.selectedTab.getTabId(); + return id ? {id, element: this.selectedTab} : undefined; } @Method() @@ -138,17 +148,6 @@ export class Tabs implements NavOutlet { 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() { const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab')); const tabPromises = tabs.map(tab => { @@ -161,7 +160,7 @@ export class Tabs implements NavOutlet { return Promise.all(tabPromises); } - private initSelect(): Promise { + private async initSelect(): Promise { if (this.useRouter) { if (Build.isDev) { 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'); } } - return Promise.resolve(); + return; } // find pre-selected tabs const selectedTab = this.tabs.find(t => t.selected) || @@ -182,14 +181,14 @@ export class Tabs implements NavOutlet { tab.selected = false; } } - const promise = selectedTab ? selectedTab.setActive() : Promise.resolve(null); - return promise.then(() => { - this.selectedTab = selectedTab; - if (selectedTab) { - selectedTab.selected = true; - selectedTab.active = true; - } - }); + if (selectedTab) { + await selectedTab.setActive(); + } + this.selectedTab = selectedTab; + if (selectedTab) { + selectedTab.selected = true; + selectedTab.active = true; + } } private loadConfig(attrKey: string, fallback: any) { diff --git a/core/src/utils/transition.ts b/core/src/utils/transition.ts index eaf64d814b..28e3e6a843 100644 --- a/core/src/utils/transition.ts +++ b/core/src/utils/transition.ts @@ -9,7 +9,7 @@ export async function transition(opts: AnimationOptions): Promise Promise); + animation?: Animation; + direction?: NavDirection; + duration?: number; + easing?: string; + viewIsReady?: () => Promise; + showGoBack?: boolean; progressAnimation?: Function; enteringEl: HTMLElement; leavingEl: HTMLElement;