mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-17 02:31:34 +08:00
refactor(nav): implement nav integration with external router (angular to start)
This commit is contained in:
@ -3,10 +3,10 @@ import {
|
||||
Directive,
|
||||
ElementRef,
|
||||
Injector,
|
||||
Optional,
|
||||
Type,
|
||||
} from '@angular/core';
|
||||
|
||||
|
||||
import { FrameworkDelegate } from '@ionic/core';
|
||||
|
||||
import { AngularComponentMounter, AngularEscapeHatch } from '..';
|
||||
@ -22,10 +22,10 @@ export class IonNav implements FrameworkDelegate {
|
||||
public elementRef: ElementRef,
|
||||
protected angularComponentMounter: AngularComponentMounter,
|
||||
protected cfr: ComponentFactoryResolver,
|
||||
protected injector: Injector) {
|
||||
protected injector: Injector
|
||||
) {
|
||||
|
||||
this.elementRef.nativeElement.delegate = this;
|
||||
|
||||
}
|
||||
|
||||
attachViewToDom(elementOrContainerToMountTo: HTMLIonNavElement,
|
||||
|
@ -22,16 +22,19 @@ import {
|
||||
Router
|
||||
} from '@angular/router';
|
||||
|
||||
import { NavResult, RouterDelegate } from '@ionic/core';
|
||||
|
||||
import { OutletInjector } from './outlet-injector';
|
||||
import { RouteEventHandler } from './route-event-handler';
|
||||
|
||||
import { AngularComponentMounter, AngularEscapeHatch } from '..';
|
||||
import { OutletInjector } from './outlet-injector';
|
||||
|
||||
let id = 0;
|
||||
|
||||
@Directive({
|
||||
selector: 'ion-nav',
|
||||
})
|
||||
export class RouterOutlet implements OnDestroy, OnInit {
|
||||
export class RouterOutlet implements OnDestroy, OnInit, RouterDelegate {
|
||||
|
||||
public name: string;
|
||||
public activationStatus = NOT_ACTIVATED;
|
||||
@ -53,12 +56,24 @@ export class RouterOutlet implements OnDestroy, OnInit {
|
||||
protected parentContexts: ChildrenOutletContexts,
|
||||
protected cfr: ComponentFactoryResolver,
|
||||
protected injector: Injector,
|
||||
protected router: Router,
|
||||
private routeEventHandler: RouteEventHandler,
|
||||
@Attribute('name') name: string) {
|
||||
|
||||
(this.elementRef.nativeElement as HTMLIonNavElement).routerDelegate = this;
|
||||
this.name = name || PRIMARY_OUTLET;
|
||||
parentContexts.onChildOutletCreated(this.name, this as any);
|
||||
}
|
||||
|
||||
pushUrlState(urlSegment: string): Promise<any> {
|
||||
return this.router.navigateByUrl(urlSegment);
|
||||
}
|
||||
|
||||
popUrlState(): Promise<any> {
|
||||
window.history.back();
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
ngOnDestroy(): void {
|
||||
console.debug(`Nav ${this.id} ngOnDestroy`);
|
||||
this.parentContexts.onChildOutletDestroyed(this.name);
|
||||
@ -93,6 +108,7 @@ export class RouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
activateWith(activatedRoute: ActivatedRoute, cfr: ComponentFactoryResolver): Promise<void> {
|
||||
this.routeEventHandler.externalNavStart();
|
||||
if (this.activationStatus !== NOT_ACTIVATED) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
@ -105,7 +121,8 @@ export class RouterOutlet implements OnDestroy, OnInit {
|
||||
const childContexts = this.parentContexts.getOrCreateContext(this.name).children;
|
||||
const injector = new OutletInjector(activatedRoute, childContexts, this.location.injector);
|
||||
|
||||
return activateRoute(this.elementRef.nativeElement, component, cfr, injector).then(() => {
|
||||
const isTopLevel = !hasChildComponent(activatedRoute);
|
||||
return activateRoute(this.elementRef.nativeElement, component, cfr, injector, isTopLevel).then(() => {
|
||||
this.changeDetector.markForCheck();
|
||||
this.activateEvents.emit(null);
|
||||
this.activationStatus = ACTIVATED;
|
||||
@ -114,16 +131,16 @@ export class RouterOutlet implements OnDestroy, OnInit {
|
||||
}
|
||||
|
||||
export function activateRoute(navElement: HTMLIonNavElement,
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector): Promise<void> {
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector, isTopLevel: boolean): Promise<void> {
|
||||
|
||||
return navElement.componentOnReady().then(() => {
|
||||
|
||||
// check if the nav has an `<ion-tab>` as a parent
|
||||
if (isParentTab(navElement)) {
|
||||
// check if the tab is selected
|
||||
return updateTab(navElement, component, cfr, injector);
|
||||
return updateTab(navElement, component, cfr, injector, isTopLevel);
|
||||
} else {
|
||||
return updateNav(navElement, component, cfr, injector);
|
||||
return updateNav(navElement, component, cfr, injector, isTopLevel);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -148,42 +165,47 @@ function getSelected(tabsElement: HTMLIonTabsElement) {
|
||||
}
|
||||
|
||||
function updateTab(navElement: HTMLIonNavElement,
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector) {
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector, isTopLevel: boolean) {
|
||||
|
||||
const tab = navElement.parentElement as HTMLIonTabElement;
|
||||
// tab.externalNav = true;
|
||||
|
||||
// (tab.parentElement as HTMLIonTabsElement).externalInitialize = true;
|
||||
// yeah yeah, I know this is kind of ugly but oh well, I know the internal structure of <ion-tabs>
|
||||
const tabs = tab.parentElement.parentElement as HTMLIonTabsElement;
|
||||
// tabs.externalInitialize = true;
|
||||
return isTabSelected(tabs, tab).then((isSelected: boolean) => {
|
||||
if (!isSelected) {
|
||||
const promise = updateNav(navElement, component, cfr, injector, isTopLevel);
|
||||
(window as any).externalNavPromise = promise
|
||||
// okay, the tab is not selected, so we need to do a "switch" transition
|
||||
// basically, we should update the nav, and then swap the tabs
|
||||
return updateNav(navElement, component, cfr, injector).then(() => {
|
||||
return promise.then(() => {
|
||||
return tabs.select(tab);
|
||||
});
|
||||
}
|
||||
|
||||
// okay cool, the tab is already selected, so we want to see a transition
|
||||
return updateNav(navElement, component, cfr, injector);
|
||||
return updateNav(navElement, component, cfr, injector, isTopLevel);
|
||||
})
|
||||
}
|
||||
|
||||
function updateNav(navElement: HTMLIonNavElement,
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector) {
|
||||
component: Type<any>, cfr: ComponentFactoryResolver, injector: Injector, isTopLevel: boolean): Promise<NavResult> {
|
||||
|
||||
const escapeHatch = getEscapeHatch(cfr, injector);
|
||||
|
||||
// check if the component is the top view
|
||||
const activeViews = navElement.getViews();
|
||||
if (activeViews.length === 0) {
|
||||
// there isn't a view in the stack, so push one
|
||||
return navElement.push(component, {}, {}, {
|
||||
cfr,
|
||||
injector
|
||||
});
|
||||
return navElement.setRoot(component, {}, {}, escapeHatch);
|
||||
}
|
||||
|
||||
const currentView = activeViews[activeViews.length - 1];
|
||||
if (currentView.component === component) {
|
||||
// the top view is already the component being activated, so there is no change needed
|
||||
return Promise.resolve();
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
// check if the component is the previous view, if so, pop back to it
|
||||
@ -192,7 +214,7 @@ function updateNav(navElement: HTMLIonNavElement,
|
||||
const previousView = activeViews[activeViews.length - 2];
|
||||
if (previousView.component === component) {
|
||||
// cool, we match the previous view, so pop it
|
||||
return navElement.pop();
|
||||
return navElement.pop(null, escapeHatch);
|
||||
}
|
||||
}
|
||||
|
||||
@ -200,17 +222,33 @@ function updateNav(navElement: HTMLIonNavElement,
|
||||
for (const view of activeViews) {
|
||||
if (view.component === component) {
|
||||
// cool, we found the match, pop back to that bad boy
|
||||
return navElement.popTo(view);
|
||||
return navElement.popTo(view, null, escapeHatch);
|
||||
}
|
||||
}
|
||||
|
||||
// since it's none of those things, we should probably just push that bad boy and call it a day
|
||||
return navElement.push(component, {}, {}, {
|
||||
cfr,
|
||||
injector
|
||||
});
|
||||
// it's the top level nav, and it's not one of those other behaviors, so do a push so the user gets a chill animation
|
||||
return navElement.push(component, {}, { animate: isTopLevel }, escapeHatch);
|
||||
}
|
||||
|
||||
export const NOT_ACTIVATED = 0;
|
||||
export const ACTIVATION_IN_PROGRESS = 1;
|
||||
export const ACTIVATED = 2;
|
||||
|
||||
export function hasChildComponent(activatedRoute: ActivatedRoute): boolean {
|
||||
// don't worry about recursion for now, that's a future problem that may or may not manifest itself
|
||||
for (const childRoute of activatedRoute.children) {
|
||||
if (childRoute.component) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function getEscapeHatch(cfr: ComponentFactoryResolver, injector: Injector): AngularEscapeHatch {
|
||||
return {
|
||||
cfr,
|
||||
injector,
|
||||
fromExternalRouter: true,
|
||||
url: location.pathname
|
||||
};
|
||||
}
|
||||
|
27
packages/angular/src/router/route-event-handler.ts
Normal file
27
packages/angular/src/router/route-event-handler.ts
Normal file
@ -0,0 +1,27 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
import {
|
||||
Event,
|
||||
NavigationEnd,
|
||||
NavigationStart,
|
||||
Router
|
||||
} from '@angular/router';
|
||||
|
||||
let initialized = false;
|
||||
|
||||
@Injectable()
|
||||
export class RouteEventHandler {
|
||||
|
||||
constructor(private router: Router) {
|
||||
(window as any).externalNav = false;
|
||||
|
||||
router.events.subscribe((event: Event) => {
|
||||
if (event instanceof NavigationEnd) {
|
||||
(window as any).externalNav = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
externalNavStart() {
|
||||
(window as any).externalNav = true;
|
||||
}
|
||||
}
|
@ -30,6 +30,7 @@ import { IonicAngularModule } from '../module';
|
||||
|
||||
import { PushPopOutletContexts } from './push-pop-outlet-contexts';
|
||||
import { CustomRouter } from './router';
|
||||
import { RouteEventHandler } from './route-event-handler';
|
||||
import { RouterOutlet } from './outlet';
|
||||
import { flatten } from './router-utils';
|
||||
|
||||
@ -62,6 +63,7 @@ export class IonicRouterModule {
|
||||
[UrlHandlingStrategy, new Optional()], [RouteReuseStrategy, new Optional()]
|
||||
]
|
||||
},
|
||||
RouteEventHandler
|
||||
]
|
||||
};
|
||||
}
|
||||
|
@ -20,8 +20,6 @@ export class CustomRouter extends Router {
|
||||
protected activateRoutes(state: Observable<{appliedUrl: string, state: RouterState, shouldActivate: boolean}>, storedState: RouterState,
|
||||
storedUrl: UrlTree, id: number, url: UrlTree, rawUrl: UrlTree, skipLocationChange: boolean, replaceUrl: boolean, resolvePromise: any, rejectPromise: any) {
|
||||
|
||||
console.log('custom activateRoutes!!!!1');
|
||||
|
||||
// applied the new router state
|
||||
// this operation has side effects
|
||||
let navigationIsSuccessful: boolean;
|
||||
|
@ -6,7 +6,7 @@ import {
|
||||
} from '@angular/core';
|
||||
import { ActivatedRoute } from '@angular/router';
|
||||
|
||||
import { FrameworkMountingData } from '@ionic/core';
|
||||
import { EscapeHatch, FrameworkMountingData} from '@ionic/core';
|
||||
|
||||
export interface AngularMountingData extends FrameworkMountingData {
|
||||
componentFactory?: ComponentFactory<any>;
|
||||
@ -16,7 +16,7 @@ export interface AngularMountingData extends FrameworkMountingData {
|
||||
angularHostElement?: HTMLElement;
|
||||
}
|
||||
|
||||
export interface AngularEscapeHatch {
|
||||
export interface AngularEscapeHatch extends EscapeHatch {
|
||||
activatedRoute?: ActivatedRoute;
|
||||
cfr?: ComponentFactoryResolver;
|
||||
injector?: Injector;
|
||||
|
646
packages/core/package-lock.json
generated
646
packages/core/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
2
packages/core/src/components.d.ts
vendored
2
packages/core/src/components.d.ts
vendored
@ -14,6 +14,7 @@ import {
|
||||
FrameworkDelegate,
|
||||
PickerColumn,
|
||||
PickerOptions,
|
||||
RouterDelegate,
|
||||
} from './index';
|
||||
import {
|
||||
AlertButton,
|
||||
@ -1837,6 +1838,7 @@ declare global {
|
||||
lazy?: boolean;
|
||||
mode?: string;
|
||||
root?: any;
|
||||
routerDelegate?: RouterDelegate;
|
||||
swipeBackEnabled?: boolean;
|
||||
useUrls?: boolean;
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,6 @@
|
||||
import { Component, Element, Listen } from '@stencil/core';
|
||||
|
||||
import { NavResult } from '../..';
|
||||
@Component({
|
||||
tag: 'ion-nav-pop',
|
||||
})
|
||||
@ -8,12 +9,12 @@ export class NavPop {
|
||||
@Element() element: HTMLElement;
|
||||
|
||||
@Listen('child:click')
|
||||
pop() {
|
||||
pop(): Promise<NavResult> {
|
||||
const nav = this.element.closest('ion-nav') as HTMLIonNavElement;
|
||||
if (nav) {
|
||||
return nav.pop();
|
||||
}
|
||||
return Promise.resolve();
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
render() {
|
||||
|
@ -36,6 +36,7 @@ export interface PublicNav {
|
||||
name?: string;
|
||||
element?: HTMLElement;
|
||||
parent?: PublicNav;
|
||||
initialized?: boolean;
|
||||
}
|
||||
|
||||
export interface NavOptions {
|
||||
@ -71,9 +72,9 @@ export interface TransitionInstruction {
|
||||
nav?: Nav;
|
||||
delegate?: FrameworkDelegate;
|
||||
animation?: Animation;
|
||||
escapeHatch?: any;
|
||||
escapeHatch?: EscapeHatch;
|
||||
method?: string;
|
||||
mountingData?: any;
|
||||
mountingData?: FrameworkMountingData;
|
||||
}
|
||||
|
||||
export interface NavResult {
|
||||
@ -86,6 +87,18 @@ export interface ComponentDataPair {
|
||||
data: any;
|
||||
}
|
||||
|
||||
export interface ExternalNavData {
|
||||
url: string;
|
||||
method: string;
|
||||
resolve: Function;
|
||||
reject: Function;
|
||||
}
|
||||
|
||||
export interface EscapeHatch {
|
||||
fromExternalRouter?: boolean;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export interface Transition extends Animation {
|
||||
enteringView?: ViewController;
|
||||
leavingView?: ViewController;
|
||||
|
@ -29,22 +29,12 @@ export let VIEW_ID_START = 2000;
|
||||
let transitionIds = 0;
|
||||
const activeTransitions = new Map<number, any>();
|
||||
|
||||
let portalZindex = 9999;
|
||||
|
||||
export function isViewController(object: any): boolean {
|
||||
return !!(object && object.didLoad && object.willUnload);
|
||||
}
|
||||
|
||||
export function setZIndex(nav: Nav, enteringView: ViewController, leavingView: ViewController, direction: string) {
|
||||
if (enteringView) {
|
||||
if (nav.isPortal) {
|
||||
if (direction === DIRECTION_FORWARD) {
|
||||
// TODO - fix typing
|
||||
updateZIndex(enteringView, (nav as any).zIndexOffset + portalZindex);
|
||||
}
|
||||
portalZindex++;
|
||||
return;
|
||||
}
|
||||
|
||||
leavingView = leavingView || nav.getPrevious(enteringView) as ViewController;
|
||||
|
||||
|
@ -5,12 +5,16 @@ import {
|
||||
AnimationOptions,
|
||||
ComponentDataPair,
|
||||
Config,
|
||||
EscapeHatch,
|
||||
ExternalNavData,
|
||||
FrameworkDelegate,
|
||||
NavOptions,
|
||||
NavOutlet,
|
||||
NavResult,
|
||||
PublicNav,
|
||||
PublicViewController,
|
||||
RouterDelegate,
|
||||
RouterEntries,
|
||||
Transition,
|
||||
TransitionInstruction,
|
||||
} from '../../index';
|
||||
@ -40,12 +44,14 @@ import {
|
||||
} from './nav-utils';
|
||||
|
||||
import { DomFrameworkDelegate } from '../../utils/dom-framework-delegate';
|
||||
import { DomRouterDelegate } from '../../utils/dom-router-delegate';
|
||||
|
||||
import {
|
||||
assert,
|
||||
focusOutActiveElement,
|
||||
isDef,
|
||||
isNumber,
|
||||
normalizeUrl,
|
||||
} from '../../utils/helpers';
|
||||
|
||||
|
||||
@ -53,8 +59,8 @@ import { buildIOSTransition } from './transitions/transition.ios';
|
||||
import { buildMdTransition } from './transitions/transition.md';
|
||||
import { GestureDetail } from '../gesture/gesture';
|
||||
|
||||
const queueMap = new Map<number, TransitionInstruction[]>();
|
||||
const urlMap = new Map<string, TransitionInstruction>();
|
||||
const transitionQueue = new Map<number, TransitionInstruction[]>();
|
||||
const allTransitionsCompleteHandlerQueue = new Map<number, Function[]>();
|
||||
|
||||
/* it is very important to keep this class in sync with ./nav-interface interface */
|
||||
@Component({
|
||||
@ -67,21 +73,23 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
@Event() navInit: EventEmitter<NavEventDetail>;
|
||||
@Event() ionNavChanged: EventEmitter<NavEventDetail>;
|
||||
|
||||
navId: number;
|
||||
init = false;
|
||||
parent: Nav;
|
||||
useRouter = false;
|
||||
navId = getNextNavId();
|
||||
routes: RouterEntries = [];
|
||||
parent: Nav = null;
|
||||
views: ViewController[] = [];
|
||||
transitioning?: boolean;
|
||||
destroyed?: boolean;
|
||||
transitionId?: number;
|
||||
isViewInitialized?: boolean;
|
||||
isPortal: boolean;
|
||||
transitioning = false;
|
||||
destroyed = false;
|
||||
transitionId = NOT_TRANSITIONING_TRANSITION_ID;
|
||||
initialized = false;
|
||||
sbTrns: any; // TODO Transition
|
||||
childNavs?: Nav[];
|
||||
urlExternalNavMap = new Map<string, ExternalNavData>();
|
||||
|
||||
@Prop() mode: string;
|
||||
@Prop() root: any;
|
||||
@Prop() delegate: FrameworkDelegate;
|
||||
@Prop() routerDelegate: RouterDelegate;
|
||||
@Prop() useUrls = false;
|
||||
@Prop({ context: 'config' }) config: Config;
|
||||
@Prop({ connect: 'ion-animation-controller' }) animationCtrl: AnimationController;
|
||||
@ -93,20 +101,15 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
}
|
||||
|
||||
componentDidLoad() {
|
||||
if (this.init) {
|
||||
return;
|
||||
}
|
||||
this.init = true;
|
||||
if (!this.lazy) {
|
||||
componentDidLoadImpl(this);
|
||||
}
|
||||
return componentDidLoadImpl(this);
|
||||
}
|
||||
|
||||
@Watch('root')
|
||||
updateRootComponent(): any {
|
||||
if (this.init) {
|
||||
updateRootComponent(): Promise<NavResult> {
|
||||
if (this.initialized) {
|
||||
return this.setRoot(this.root);
|
||||
}
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
@Method()
|
||||
@ -115,52 +118,52 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
}
|
||||
|
||||
@Method()
|
||||
push(component: any, data?: any, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
push(component: any, data?: any, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return pushImpl(this, component, data, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
pop(opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
pop(opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return popImpl(this, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
setRoot(component: any, data?: any, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
setRoot(component: any, data?: any, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return setRootImpl(this, component, data, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
insert(insertIndex: number, page: any, params?: any, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
insert(insertIndex: number, page: any, params?: any, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return insertImpl(this, insertIndex, page, params, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return insertPagesImpl(this, insertIndex, insertPages, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
popToRoot(opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
popToRoot(opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return popToRootImpl(this, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
popTo(indexOrViewCtrl: any, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
popTo(indexOrViewCtrl: any, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return popToImpl(this, indexOrViewCtrl, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
removeIndex(startIndex: number, removeCount?: number, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
removeIndex(startIndex: number, removeCount?: number, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return removeImpl(this, startIndex, removeCount, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
removeView(viewController: PublicViewController, opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
removeView(viewController: PublicViewController, opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return removeViewImpl(this, viewController, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@Method()
|
||||
setPages(componentDataPairs: ComponentDataPair[], opts?: NavOptions, escapeHatch: any = {}): Promise<any> {
|
||||
setPages(componentDataPairs: ComponentDataPair[], opts?: NavOptions, escapeHatch: EscapeHatch = getDefaultEscapeHatch()): Promise<NavResult> {
|
||||
return setPagesImpl(this, componentDataPairs, opts, escapeHatch);
|
||||
}
|
||||
|
||||
@ -190,10 +193,11 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
}
|
||||
|
||||
@Method()
|
||||
setRouteId(id: string, _: any = {}): Promise<void> {
|
||||
setRouteId(id: string, _: any = {}): Promise<any> {
|
||||
assert(this.useRouter, 'routing is disabled');
|
||||
const active = this.getActive();
|
||||
if (active && active.component === id) {
|
||||
return Promise.resolve();
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
return this.setRoot(id);
|
||||
}
|
||||
@ -224,7 +228,7 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
|
||||
@Method()
|
||||
isTransitioning() {
|
||||
return !!this.transitionId;
|
||||
return this.transitionId >= 0;
|
||||
}
|
||||
|
||||
@Method()
|
||||
@ -238,13 +242,8 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
}
|
||||
|
||||
@Method()
|
||||
getTransitionInfoForUrl(url: string): TransitionInstruction {
|
||||
return urlMap.get(url);
|
||||
}
|
||||
|
||||
@Method()
|
||||
clearTransitionInfoForUrl(url: string) {
|
||||
urlMap.delete(url);
|
||||
onAllTransitionsComplete() {
|
||||
return allTransitionsCompleteImpl(this);
|
||||
}
|
||||
|
||||
canSwipeBack(): boolean {
|
||||
@ -330,48 +329,60 @@ export class Nav implements PublicNav, NavOutlet {
|
||||
}
|
||||
|
||||
export function componentDidLoadImpl(nav: Nav) {
|
||||
if (nav.initialized) {
|
||||
return;
|
||||
}
|
||||
nav.initialized = true;
|
||||
nav.navInit.emit();
|
||||
if (nav.root) {
|
||||
nav.setRoot(nav.root);
|
||||
if (!nav.useRouter) {
|
||||
if (nav.root && !nav.lazy) {
|
||||
nav.setRoot(nav.root);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function pushImpl(nav: Nav, component: any, data: any, opts: NavOptions, escapeHatch: any) {
|
||||
export async function pushImpl(nav: Nav, component: any, data: any, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return push(nav, nav.delegate, animation, component, data, opts, escapeHatch);
|
||||
return push(nav, nav.delegate, animation, component, data, opts, escapeHatch).then((navResult) => {
|
||||
return navResult;
|
||||
});
|
||||
}
|
||||
|
||||
export async function popImpl(nav: Nav, opts: NavOptions, escapeHatch: any) {
|
||||
export async function popImpl(nav: Nav, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return pop(nav, nav.delegate, animation, opts, escapeHatch);
|
||||
return pop(nav, nav.delegate, animation, opts, escapeHatch).then((navResult) => {
|
||||
return navResult;
|
||||
});
|
||||
}
|
||||
|
||||
export async function setRootImpl(nav: Nav, component: any, data: any, opts: NavOptions, escapeHatch: any) {
|
||||
export async function setRootImpl(nav: Nav, component: any, data: any, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return setRoot(nav, nav.delegate, animation, component, data, opts, escapeHatch);
|
||||
return setRoot(nav, nav.delegate, animation, component, data, opts, escapeHatch).then((navResult) => {
|
||||
return navResult;
|
||||
});
|
||||
}
|
||||
|
||||
export async function insertImpl(nav: Nav, insertIndex: number, page: any, params: any, opts: NavOptions, escapeHatch: any) {
|
||||
export async function insertImpl(nav: Nav, insertIndex: number, page: any, params: any, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return insert(nav, nav.delegate, animation, insertIndex, page, params, opts, escapeHatch);
|
||||
}
|
||||
|
||||
export async function insertPagesImpl(nav: Nav, insertIndex: number, pagesToInsert: any[], opts: NavOptions, escapeHatch: any) {
|
||||
export async function insertPagesImpl(nav: Nav, insertIndex: number, pagesToInsert: any[], opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return insertPages(nav, nav.delegate, animation, insertIndex, pagesToInsert, opts, escapeHatch);
|
||||
}
|
||||
|
||||
export async function popToRootImpl(nav: Nav, opts: NavOptions, escapeHatch: any) {
|
||||
export async function popToRootImpl(nav: Nav, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return popToRoot(nav, nav.delegate, animation, opts, escapeHatch);
|
||||
}
|
||||
|
||||
export async function popToImpl(nav: Nav, indexOrViewCtrl: any, opts: NavOptions, escapeHatch: any) {
|
||||
export async function popToImpl(nav: Nav, indexOrViewCtrl: any, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return popTo(nav, nav.delegate, animation, indexOrViewCtrl, opts, escapeHatch);
|
||||
}
|
||||
|
||||
export async function removeImpl(nav: Nav, startIndex: number, removeCount: number, opts: NavOptions, escapeHatch: any) {
|
||||
export async function removeImpl(nav: Nav, startIndex: number, removeCount: number, opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return remove(nav, nav.delegate, animation, startIndex, removeCount, opts, escapeHatch);
|
||||
}
|
||||
@ -381,9 +392,9 @@ export async function removeViewImpl(nav: Nav, viewController: PublicViewControl
|
||||
return removeView(nav, nav.delegate, animation, viewController as ViewController, opts, escapeHatch);
|
||||
}
|
||||
|
||||
export async function setPagesImpl(nav: Nav, componentDataPairs: ComponentDataPair[], opts: NavOptions, escapeHatch: any) {
|
||||
export async function setPagesImpl(nav: Nav, componentDataPairs: ComponentDataPair[], opts: NavOptions, escapeHatch: EscapeHatch) {
|
||||
const animation = await hydrateAnimationController(nav.animationCtrl);
|
||||
return setPages(nav, nav.delegate, animation, componentDataPairs, opts, escapeHatch);
|
||||
return setPages(nav, nav.delegate, animation, componentDataPairs, opts, escapeHatch, null);
|
||||
}
|
||||
|
||||
export function canGoBackImpl(nav: Nav) {
|
||||
@ -407,11 +418,10 @@ export function hydrateAnimationController(animationController: AnimationControl
|
||||
return animationController.create();
|
||||
}
|
||||
|
||||
|
||||
// public api
|
||||
|
||||
export function push(nav: Nav, delegate: FrameworkDelegate, animation: Animation, component: any, data: any, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function push(nav: Nav, delegate: FrameworkDelegate, animation: Animation, component: any, data: any, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: component,
|
||||
insertStart: -1,
|
||||
insertViews: [{component, data}],
|
||||
@ -421,12 +431,12 @@ export function push(nav: Nav, delegate: FrameworkDelegate, animation: Animation
|
||||
id: nav.navId,
|
||||
animation,
|
||||
escapeHatch,
|
||||
method: 'push'
|
||||
method: PUSH
|
||||
});
|
||||
}
|
||||
|
||||
export function insert(nav: Nav, delegate: FrameworkDelegate, animation: Animation, insertIndex: number, component: any, data: any, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function insert(nav: Nav, delegate: FrameworkDelegate, animation: Animation, insertIndex: number, component: any, data: any, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: component,
|
||||
insertStart: insertIndex,
|
||||
insertViews: [{ component, data }],
|
||||
@ -440,8 +450,8 @@ export function insert(nav: Nav, delegate: FrameworkDelegate, animation: Animati
|
||||
});
|
||||
}
|
||||
|
||||
export function insertPages(nav: Nav, delegate: FrameworkDelegate, animation: Animation, insertIndex: number, insertPages: any[], opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function insertPages(nav: Nav, delegate: FrameworkDelegate, animation: Animation, insertIndex: number, insertPages: any[], opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: null,
|
||||
insertStart: insertIndex,
|
||||
insertViews: insertPages,
|
||||
@ -455,8 +465,8 @@ export function insertPages(nav: Nav, delegate: FrameworkDelegate, animation: An
|
||||
});
|
||||
}
|
||||
|
||||
export function pop(nav: Nav, delegate: FrameworkDelegate, animation: Animation, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function pop(nav: Nav, delegate: FrameworkDelegate, animation: Animation, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: null,
|
||||
removeStart: -1,
|
||||
removeCount: 1,
|
||||
@ -466,12 +476,12 @@ export function pop(nav: Nav, delegate: FrameworkDelegate, animation: Animation,
|
||||
id: nav.navId,
|
||||
animation,
|
||||
escapeHatch,
|
||||
method: 'pop'
|
||||
method: POP
|
||||
});
|
||||
}
|
||||
|
||||
export function popToRoot(nav: Nav, delegate: FrameworkDelegate, animation: Animation, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function popToRoot(nav: Nav, delegate: FrameworkDelegate, animation: Animation, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: null,
|
||||
removeStart: 1,
|
||||
removeCount: -1,
|
||||
@ -485,7 +495,7 @@ export function popToRoot(nav: Nav, delegate: FrameworkDelegate, animation: Anim
|
||||
});
|
||||
}
|
||||
|
||||
export function popTo(nav: Nav, delegate: FrameworkDelegate, animation: Animation, indexOrViewCtrl: any, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
export function popTo(nav: Nav, delegate: FrameworkDelegate, animation: Animation, indexOrViewCtrl: any, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
const config: TransitionInstruction = {
|
||||
component: null,
|
||||
removeStart: -1,
|
||||
@ -504,11 +514,11 @@ export function popTo(nav: Nav, delegate: FrameworkDelegate, animation: Animatio
|
||||
} else if (isNumber(indexOrViewCtrl)) {
|
||||
config.removeStart = indexOrViewCtrl + 1;
|
||||
}
|
||||
return queueTransaction(config);
|
||||
return preprocessTransaction(config);
|
||||
}
|
||||
|
||||
export function remove(nav: Nav, delegate: FrameworkDelegate, animation: Animation, startIndex: number, removeCount = 1, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function remove(nav: Nav, delegate: FrameworkDelegate, animation: Animation, startIndex: number, removeCount = 1, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: null,
|
||||
removeStart: startIndex,
|
||||
removeCount: removeCount,
|
||||
@ -522,8 +532,8 @@ export function remove(nav: Nav, delegate: FrameworkDelegate, animation: Animati
|
||||
});
|
||||
}
|
||||
|
||||
export function removeView(nav: Nav, delegate: FrameworkDelegate, animation: Animation, viewController: ViewController, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return queueTransaction({
|
||||
export function removeView(nav: Nav, delegate: FrameworkDelegate, animation: Animation, viewController: ViewController, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return preprocessTransaction({
|
||||
component: null,
|
||||
removeView: viewController,
|
||||
removeStart: 0,
|
||||
@ -538,18 +548,18 @@ export function removeView(nav: Nav, delegate: FrameworkDelegate, animation: Ani
|
||||
});
|
||||
}
|
||||
|
||||
export function setRoot(nav: Nav, delegate: FrameworkDelegate, animation: Animation, component: any, data: any, opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
return setPages(nav, delegate, animation, [{ component, data }], opts, escapeHatch);
|
||||
export function setRoot(nav: Nav, delegate: FrameworkDelegate, animation: Animation, component: any, data: any, opts: NavOptions, escapeHatch: EscapeHatch): Promise<NavResult> {
|
||||
return setPages(nav, delegate, animation, [{ component, data }], opts, escapeHatch, SET_ROOT);
|
||||
}
|
||||
|
||||
export function setPages(nav: Nav, delegate: FrameworkDelegate, animation: Animation, componentDataPairs: ComponentDataPair[], opts: NavOptions, escapeHatch: any): Promise<any> {
|
||||
export function setPages(nav: Nav, delegate: FrameworkDelegate, animation: Animation, componentDataPairs: ComponentDataPair[], opts: NavOptions, escapeHatch: EscapeHatch, methodName: string): Promise<NavResult> {
|
||||
if (!isDef(opts)) {
|
||||
opts = {};
|
||||
}
|
||||
if (opts.animate !== true) {
|
||||
opts.animate = false;
|
||||
}
|
||||
return queueTransaction({
|
||||
return preprocessTransaction({
|
||||
component: componentDataPairs.length === 1 ? componentDataPairs[0].component : null,
|
||||
insertStart: 0,
|
||||
insertViews: componentDataPairs,
|
||||
@ -561,22 +571,49 @@ export function setPages(nav: Nav, delegate: FrameworkDelegate, animation: Anima
|
||||
id: nav.navId,
|
||||
animation,
|
||||
escapeHatch,
|
||||
method: 'setPages'
|
||||
method: methodName ? methodName : 'setPages'
|
||||
});
|
||||
}
|
||||
|
||||
// private api, exported for testing
|
||||
|
||||
export function queueOrNavigate(ti: TransitionInstruction): void | Promise<NavResult> {
|
||||
if (isComponentUrl(ti.component)) {
|
||||
urlMap.set(ti.component as string, ti);
|
||||
window.location.href = ti.component;
|
||||
export function preprocessTransaction(ti: TransitionInstruction): Promise<NavResult> {
|
||||
if (isUrl(ti.component)) {
|
||||
if (ti.method === PUSH || ti.method === POP || ti.method === SET_ROOT) {
|
||||
return navigateToUrl(ti.nav, normalizeUrl(ti.component) as string, ti.method);
|
||||
} else {
|
||||
return Promise.reject(new Error('only push, pop, and setRoot methods support urls'));
|
||||
}
|
||||
}
|
||||
|
||||
const response = checkIfPopRedirectRequired(ti);
|
||||
if (response.required) {
|
||||
return navigateToUrl(ti.nav, response.url, POP);
|
||||
}
|
||||
|
||||
return queueTransaction(ti);
|
||||
}
|
||||
|
||||
export function isComponentUrl(component: any) {
|
||||
return component && typeof component === 'string' && component.charAt(0) === '/';
|
||||
export function isUrl(component: any): boolean {
|
||||
return typeof component === 'string' && component.charAt(0) === '/';
|
||||
}
|
||||
|
||||
export function navigateToUrl(nav: Nav, url: string, method: string): Promise<NavResult> {
|
||||
let routingPromise: Promise<any> = null;
|
||||
return new Promise((resolve, reject) => {
|
||||
nav.urlExternalNavMap.set(url, {
|
||||
url,
|
||||
method,
|
||||
resolve,
|
||||
reject
|
||||
});
|
||||
if (!nav.routerDelegate) {
|
||||
nav.routerDelegate = new DomRouterDelegate();
|
||||
}
|
||||
routingPromise = nav.routerDelegate.pushUrlState(url);
|
||||
}).then((navResult: NavResult) => {
|
||||
return routingPromise.then(() => {
|
||||
return navResult;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
export function queueTransaction(ti: TransitionInstruction): Promise<NavResult> {
|
||||
@ -617,16 +654,68 @@ export function nextTransaction(nav: Nav): Promise<any> {
|
||||
|
||||
const topTransaction = getTopTransaction(nav.navId);
|
||||
if (!topTransaction) {
|
||||
// cool, there are no transitions going for this nav
|
||||
processAllTransitionCompleteQueue(nav.navId);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
return doNav(nav, topTransaction);
|
||||
}
|
||||
|
||||
export function checkIfPopRedirectRequired(ti: TransitionInstruction): IsRedirectRequired {
|
||||
if (ti.method === POP) {
|
||||
|
||||
if (ti.escapeHatch.fromExternalRouter) {
|
||||
// if the pop method is called from a router, that means the redirect already happened
|
||||
// so just do a normal pop because the url is in a good place. Basically, the router is telling us to
|
||||
// pop
|
||||
return {
|
||||
required: false
|
||||
};
|
||||
}
|
||||
|
||||
// check if we need to redirect to a url for the pop operation
|
||||
const popToIndex = ti.nav.views.length - 2;
|
||||
if (popToIndex >= 0) {
|
||||
const viewController = ti.nav.views[popToIndex];
|
||||
return {
|
||||
required: viewController.fromExternalRouter,
|
||||
url: viewController.url
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
required: false,
|
||||
};
|
||||
}
|
||||
|
||||
export function processAllTransitionCompleteQueue(navId: number) {
|
||||
const queue = allTransitionsCompleteHandlerQueue.get(navId) || [];
|
||||
for (const callback of queue) {
|
||||
callback();
|
||||
}
|
||||
allTransitionsCompleteHandlerQueue.set(navId, []);
|
||||
}
|
||||
|
||||
export function allTransitionsCompleteImpl(nav: Nav) {
|
||||
return new Promise((resolve) => {
|
||||
const queue = transitionQueue.get(nav.navId) || [];
|
||||
if (queue.length) {
|
||||
// there are pending transitions, so queue it up and we'll be notified when it's done
|
||||
const handlers = allTransitionsCompleteHandlerQueue.get(nav.navId) || [];
|
||||
handlers.push(resolve);
|
||||
return allTransitionsCompleteHandlerQueue.set(nav.navId, handlers);
|
||||
}
|
||||
// there are no pending transitions, so just resolve right away
|
||||
return resolve();
|
||||
});
|
||||
}
|
||||
|
||||
export function doNav(nav: Nav, ti: TransitionInstruction) {
|
||||
let enteringView: ViewController;
|
||||
let leavingView: ViewController;
|
||||
return initializeViewBeforeTransition(nav, ti).then(([_enteringView, _leavingView]) => {
|
||||
return initializeViewBeforeTransition(ti).then(([_enteringView, _leavingView]) => {
|
||||
enteringView = _enteringView;
|
||||
leavingView = _leavingView;
|
||||
return attachViewToDom(nav, enteringView, ti);
|
||||
@ -647,8 +736,8 @@ export function successfullyTransitioned(ti: TransitionInstruction) {
|
||||
return fireError(new Error('Queue is null, the nav must have been destroyed'), ti);
|
||||
}
|
||||
|
||||
ti.nav.isViewInitialized = true;
|
||||
ti.nav.transitionId = null;
|
||||
ti.nav.initialized = true;
|
||||
ti.nav.transitionId = NOT_TRANSITIONING_TRANSITION_ID;
|
||||
ti.nav.transitioning = false;
|
||||
|
||||
// TODO - check if it's a swipe back
|
||||
@ -739,7 +828,7 @@ export function loadViewAndTransition(nav: Nav, enteringView: ViewController, le
|
||||
|
||||
export function executeAsyncTransition(nav: Nav, transition: Transition, enteringView: ViewController, leavingView: ViewController, delegate: FrameworkDelegate, opts: NavOptions, configShouldAnimate: boolean): Promise<void> {
|
||||
assert(nav.transitioning, 'must be transitioning');
|
||||
nav.transitionId = null;
|
||||
nav.transitionId = NOT_TRANSITIONING_TRANSITION_ID;
|
||||
setZIndex(nav, enteringView, leavingView, opts.direction);
|
||||
|
||||
// always ensure the entering view is viewable
|
||||
@ -751,8 +840,8 @@ export function executeAsyncTransition(nav: Nav, transition: Transition, enterin
|
||||
// ******** DOM WRITE ****************
|
||||
leavingView && toggleHidden(leavingView.element, false);
|
||||
|
||||
const isFirstPage = !nav.isViewInitialized && nav.views.length === 1;
|
||||
const shouldNotAnimate = isFirstPage && !nav.isPortal;
|
||||
const isFirstPage = !nav.initialized && nav.views.length === 1;
|
||||
const shouldNotAnimate = isFirstPage;
|
||||
if (configShouldAnimate || shouldNotAnimate) {
|
||||
opts.animate = false;
|
||||
}
|
||||
@ -847,7 +936,7 @@ export function cleanUpView(nav: Nav, delegate: FrameworkDelegate, activeViewCon
|
||||
// this view comes after the active view
|
||||
inactiveViewController.willUnload();
|
||||
promises.push(destroyView(nav, delegate, inactiveViewController));
|
||||
} else if ( i < activeIndex && !nav.isPortal) {
|
||||
} else if ( i < activeIndex) {
|
||||
// this view comes before the active view
|
||||
// and it is not a portal then ensure it is hidden
|
||||
toggleHidden(inactiveViewController.element, true);
|
||||
@ -875,11 +964,11 @@ export function attachViewToDom(nav: Nav, enteringView: ViewController, ti: Tran
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
export function initializeViewBeforeTransition(nav: Nav, ti: TransitionInstruction): Promise<ViewController[]> {
|
||||
export function initializeViewBeforeTransition(ti: TransitionInstruction): Promise<ViewController[]> {
|
||||
let leavingView: ViewController = null;
|
||||
let enteringView: ViewController = null;
|
||||
return startTransaction(ti).then(() => {
|
||||
const viewControllers = convertComponentToViewController(nav, ti);
|
||||
const viewControllers = convertComponentToViewController(ti);
|
||||
ti.viewControllers = viewControllers;
|
||||
leavingView = ti.nav.getActive() as ViewController;
|
||||
enteringView = getEnteringView(ti, ti.nav, leavingView);
|
||||
@ -925,7 +1014,7 @@ export function updateNavStacks(enteringView: ViewController, leavingView: ViewC
|
||||
|
||||
const finalBalance = ti.nav.views.length + (ti.insertViews ? ti.insertViews.length : 0) - (ti.removeCount ? ti.removeCount : 0);
|
||||
assert(finalBalance >= 0, 'final balance can not be negative');
|
||||
if (finalBalance === 0 && !ti.nav.isPortal) {
|
||||
if (finalBalance === 0) {
|
||||
console.warn(`You can't remove all the pages in the navigation stack. nav.pop() is probably called too many times.`);
|
||||
throw new Error('Navigation stack needs at least one root page');
|
||||
}
|
||||
@ -1001,7 +1090,7 @@ export function insertViewIntoNav(nav: Nav, view: ViewController, index: number)
|
||||
assert(view.nav === nav, 'view is not part of the nav');
|
||||
nav.views.splice(index, 0, nav.views.splice(existingIndex, 1)[0]);
|
||||
} else {
|
||||
assert(!view.nav || (nav.isPortal && view.nav === nav), 'nav is used');
|
||||
assert(!view.nav, 'nav is used');
|
||||
// this is a new view to add to the stack
|
||||
// create the new entering view
|
||||
view.nav = nav;
|
||||
@ -1117,17 +1206,18 @@ export function getEnteringView(ti: TransitionInstruction, nav: Nav, leavingView
|
||||
return null;
|
||||
}
|
||||
|
||||
export function convertViewsToViewControllers(pairs: ComponentDataPair[]): ViewController[] {
|
||||
export function convertViewsToViewControllers(pairs: ComponentDataPair[], escapeHatch: EscapeHatch): ViewController[] {
|
||||
return pairs.filter(pair => !!pair)
|
||||
.map(pair => {
|
||||
return new ViewController(pair.component, pair.data);
|
||||
const applyEscapeHatch = pair === pairs[pairs.length - 1];
|
||||
return new ViewController(pair.component, pair.data, applyEscapeHatch ? escapeHatch.fromExternalRouter : false, applyEscapeHatch ? escapeHatch.url : null);
|
||||
});
|
||||
}
|
||||
|
||||
export function convertComponentToViewController(_: Nav, ti: TransitionInstruction): ViewController[] {
|
||||
export function convertComponentToViewController(ti: TransitionInstruction): ViewController[] {
|
||||
if (ti.insertViews) {
|
||||
assert(ti.insertViews.length > 0, 'length can not be zero');
|
||||
const viewControllers = convertViewsToViewControllers(ti.insertViews);
|
||||
const viewControllers = convertViewsToViewControllers(ti.insertViews, ti.escapeHatch);
|
||||
assert(ti.insertViews.length === viewControllers.length, 'lengths does not match');
|
||||
if (viewControllers.length === 0) {
|
||||
throw new Error('No views to insert');
|
||||
@ -1147,17 +1237,17 @@ export function convertComponentToViewController(_: Nav, ti: TransitionInstructi
|
||||
}
|
||||
|
||||
export function addToQueue(ti: TransitionInstruction) {
|
||||
const list = queueMap.get(ti.id) || [];
|
||||
const list = transitionQueue.get(ti.id) || [];
|
||||
list.push(ti);
|
||||
queueMap.set(ti.id, list);
|
||||
transitionQueue.set(ti.id, list);
|
||||
}
|
||||
|
||||
export function getQueue(id: number) {
|
||||
return queueMap.get(id) || [];
|
||||
return transitionQueue.get(id) || [];
|
||||
}
|
||||
|
||||
export function resetQueue(id: number) {
|
||||
queueMap.set(id, []);
|
||||
transitionQueue.set(id, []);
|
||||
}
|
||||
|
||||
export function getTopTransaction(id: number) {
|
||||
@ -1167,7 +1257,7 @@ export function getTopTransaction(id: number) {
|
||||
}
|
||||
const tmp = queue.concat();
|
||||
const toReturn = tmp.shift();
|
||||
queueMap.set(id, tmp);
|
||||
transitionQueue.set(id, tmp);
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@ -1177,6 +1267,7 @@ export function getDefaultTransition(config: Config) {
|
||||
|
||||
let viewIds = VIEW_ID_START;
|
||||
const DISABLE_APP_MINIMUM_DURATION = 64;
|
||||
const NOT_TRANSITIONING_TRANSITION_ID = -1;
|
||||
|
||||
export interface NavEvent extends CustomEvent {
|
||||
target: HTMLIonNavElement;
|
||||
@ -1186,3 +1277,18 @@ export interface NavEvent extends CustomEvent {
|
||||
export interface NavEventDetail {
|
||||
isPop?: boolean;
|
||||
}
|
||||
|
||||
export function getDefaultEscapeHatch(): EscapeHatch {
|
||||
return {
|
||||
fromExternalRouter: false,
|
||||
};
|
||||
}
|
||||
|
||||
export interface IsRedirectRequired {
|
||||
required: boolean;
|
||||
url?: string;
|
||||
}
|
||||
|
||||
export const POP = 'pop';
|
||||
export const PUSH = 'push';
|
||||
export const SET_ROOT = 'setRoot';
|
||||
|
@ -27,6 +27,11 @@ string
|
||||
any
|
||||
|
||||
|
||||
#### routerDelegate
|
||||
|
||||
|
||||
|
||||
|
||||
#### swipeBackEnabled
|
||||
|
||||
boolean
|
||||
@ -59,6 +64,11 @@ string
|
||||
any
|
||||
|
||||
|
||||
#### router-delegate
|
||||
|
||||
|
||||
|
||||
|
||||
#### swipe-back-enabled
|
||||
|
||||
boolean
|
||||
@ -82,9 +92,6 @@ boolean
|
||||
#### canGoBack()
|
||||
|
||||
|
||||
#### clearTransitionInfoForUrl()
|
||||
|
||||
|
||||
#### first()
|
||||
|
||||
|
||||
@ -106,9 +113,6 @@ boolean
|
||||
#### getRouteId()
|
||||
|
||||
|
||||
#### getTransitionInfoForUrl()
|
||||
|
||||
|
||||
#### getViews()
|
||||
|
||||
|
||||
@ -124,6 +128,9 @@ boolean
|
||||
#### last()
|
||||
|
||||
|
||||
#### onAllTransitionsComplete()
|
||||
|
||||
|
||||
#### pop()
|
||||
|
||||
|
||||
|
@ -14,10 +14,10 @@ const SHOW_BACK_BTN_CSS = 'show-back-button';
|
||||
export function buildIOSTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise<Transition> {
|
||||
const componentReadyPromise: Promise<any>[] = [];
|
||||
// Let makes sure everything is hydrated and ready to animate
|
||||
if (enteringView) {
|
||||
if (enteringView && (enteringView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((enteringView.element as any).componentOnReady());
|
||||
}
|
||||
if (leavingView) {
|
||||
if (leavingView && (leavingView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((leavingView.element as any).componentOnReady());
|
||||
}
|
||||
|
||||
|
@ -10,10 +10,10 @@ const SHOW_BACK_BTN_CSS = 'show-back-button';
|
||||
export function buildMdTransition(rootTransition: Transition, enteringView: ViewController, leavingView: ViewController, opts: AnimationOptions): Promise<Transition> {
|
||||
|
||||
const componentReadyPromise: Promise<any>[] = [];
|
||||
if (enteringView) {
|
||||
if (enteringView && (enteringView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((enteringView.element as any).componentOnReady());
|
||||
}
|
||||
if (leavingView) {
|
||||
if (leavingView && (leavingView.element as any).componentOnReady) {
|
||||
componentReadyPromise.push((leavingView.element as any).componentOnReady());
|
||||
}
|
||||
|
||||
@ -32,8 +32,7 @@ export function buildMdTransition(rootTransition: Transition, enteringView: View
|
||||
// animate the component itself
|
||||
if (backDirection) {
|
||||
rootTransition.duration(isDef(opts.duration) ? opts.duration : 200).easing('cubic-bezier(0.47,0,0.745,0.715)');
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
rootTransition.duration(isDef(opts.duration) ? opts.duration : 280).easing('cubic-bezier(0.36,0.66,0.04,1)');
|
||||
|
||||
rootTransition
|
||||
|
@ -1,7 +1,10 @@
|
||||
import { FrameworkDelegate, Nav, PublicViewController } from '../../index';
|
||||
import { STATE_ATTACHED, STATE_DESTROYED, STATE_INITIALIZED, STATE_NEW } from './nav-utils';
|
||||
|
||||
import { assert } from '../../utils/helpers';
|
||||
import {
|
||||
assert,
|
||||
normalizeUrl
|
||||
} from '../../utils/helpers';
|
||||
|
||||
export class ViewController implements PublicViewController {
|
||||
|
||||
@ -15,13 +18,15 @@ export class ViewController implements PublicViewController {
|
||||
zIndex: number;
|
||||
dismissProxy: any;
|
||||
timestamp: number;
|
||||
fromExternalRouter: boolean;
|
||||
url: string;
|
||||
|
||||
|
||||
onDidDismiss: (data: any, role: string) => void;
|
||||
onWillDismiss: (data: any, role: string) => void;
|
||||
|
||||
constructor(public component: any, data?: any) {
|
||||
initializeNewViewController(this, data);
|
||||
constructor(public component: any, data: any, fromExternalRouter: boolean, url: string) {
|
||||
initializeNewViewController(this, data, fromExternalRouter, url);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -159,8 +164,10 @@ export function didLoadImpl(viewController: ViewController) {
|
||||
callLifeCycleFunction(viewController.instance, 'ionViewDidLoad');
|
||||
}
|
||||
|
||||
export function initializeNewViewController(viewController: ViewController, data: any) {
|
||||
export function initializeNewViewController(viewController: ViewController, data: any, fromExternalRouter: boolean, url: string) {
|
||||
viewController.timestamp = Date.now();
|
||||
viewController.state = STATE_NEW;
|
||||
viewController.data = data || {};
|
||||
viewController.fromExternalRouter = fromExternalRouter;
|
||||
viewController.url = url && normalizeUrl(url);
|
||||
}
|
||||
|
@ -1,5 +1,5 @@
|
||||
export interface NavOutlet {
|
||||
setRouteId(id: any, data?: any): Promise<void>;
|
||||
setRouteId(id: any, data?: any): Promise<any>;
|
||||
getRouteId(): string;
|
||||
getContentElement(): HTMLElement | null;
|
||||
}
|
||||
|
@ -1,5 +1,4 @@
|
||||
import { Component, Element, Event, EventEmitter, Method, Prop, State, Watch } from '@stencil/core';
|
||||
|
||||
import { getNavAsChildIfExists } from '../../utils/helpers';
|
||||
import { FrameworkDelegate } from '../..';
|
||||
|
||||
@ -9,7 +8,7 @@ import { FrameworkDelegate } from '../..';
|
||||
})
|
||||
export class Tab {
|
||||
|
||||
private loaded = false;
|
||||
// private loaded = false;
|
||||
@Element() el: HTMLElement;
|
||||
|
||||
@State() init = false;
|
||||
@ -66,6 +65,7 @@ export class Tab {
|
||||
|
||||
@Prop({ mutable: true }) selected = false;
|
||||
|
||||
|
||||
@Watch('selected')
|
||||
selectedChanged(selected: boolean) {
|
||||
if (selected) {
|
||||
@ -81,7 +81,30 @@ export class Tab {
|
||||
@Method()
|
||||
setActive(active: boolean): Promise<any> {
|
||||
this.active = active;
|
||||
if (this.loaded || !active) {
|
||||
if (active) {
|
||||
const nav = getNavAsChildIfExists(this.el);
|
||||
if (nav) {
|
||||
// the tab's nav has been initialized externally
|
||||
if ((window as any).externalNavPromise) {
|
||||
return (window as any).externalNavPromise.then(() => {
|
||||
(window as any).externalNavPromise = null;
|
||||
});
|
||||
} else {
|
||||
// the tab's nav has not been initialized externally, so
|
||||
// check if we need to initiailize it
|
||||
return (nav as any).componentOnReady().then(() => {
|
||||
return nav.onAllTransitionsComplete();
|
||||
}).then(() => {
|
||||
if (!nav.getViews().length && !nav.isTransitioning() && !nav.initialized) {
|
||||
return nav.setRoot(nav.root);
|
||||
}
|
||||
return Promise.resolve();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*if (this.loaded || !active) {
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@ -97,6 +120,8 @@ export class Tab {
|
||||
promise = Promise.resolve();
|
||||
}
|
||||
return promise.then(() => this.fireChildren());
|
||||
*/
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
@Method()
|
||||
@ -110,7 +135,7 @@ export class Tab {
|
||||
return null;
|
||||
}
|
||||
|
||||
private fireChildren() {
|
||||
/*private fireChildren() {
|
||||
const nav = getNavAsChildIfExists(this.el);
|
||||
if (nav && nav.getViews().length === 0 && nav.root) {
|
||||
// we need to initialize
|
||||
@ -119,6 +144,7 @@ export class Tab {
|
||||
// it's already been initialized if it exists
|
||||
return Promise.resolve();
|
||||
}
|
||||
*/
|
||||
|
||||
hostData() {
|
||||
const visible = this.active && this.selected;
|
||||
@ -127,7 +153,7 @@ export class Tab {
|
||||
'aria-labelledby': this.btnId,
|
||||
'role': 'tabpanel',
|
||||
class: {
|
||||
'show-tab': this.active
|
||||
'show-tab': visible
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -137,14 +163,15 @@ export class Tab {
|
||||
}
|
||||
}
|
||||
|
||||
function attachViewToDom(container: HTMLElement, cmp: string): Promise<any> {
|
||||
/*function attachViewToDom(container: HTMLElement, cmp: string): Promise<any> {
|
||||
const el = document.createElement(cmp) as HTMLStencilElement;
|
||||
container.appendChild(el);
|
||||
if (el.componentOnReady ) {
|
||||
if (el.componentOnReady) {
|
||||
return el.componentOnReady();
|
||||
}
|
||||
return Promise.resolve();
|
||||
}
|
||||
*/
|
||||
|
||||
export interface TabEvent extends CustomEvent {
|
||||
detail: TabEventDetail;
|
||||
|
@ -9,6 +9,7 @@ import { Config, NavEventDetail, NavOutlet } from '../../index';
|
||||
export class Tabs implements NavOutlet {
|
||||
private ids = -1;
|
||||
private tabsId: number = (++tabIds);
|
||||
initialized = false;
|
||||
|
||||
@Element() el: HTMLElement;
|
||||
|
||||
@ -70,8 +71,14 @@ export class Tabs implements NavOutlet {
|
||||
this.loadConfig('tabsLayout', 'icon-top');
|
||||
this.loadConfig('tabsHighlight', true);
|
||||
|
||||
this.initTabs();
|
||||
this.initSelect();
|
||||
return this.initTabs().then(() => {
|
||||
if (! (window as any).externalNav) {
|
||||
return this.initSelect();
|
||||
}
|
||||
return null;
|
||||
}).then(() => {
|
||||
this.initialized = true;
|
||||
});
|
||||
}
|
||||
|
||||
componentDidUnload() {
|
||||
@ -171,16 +178,19 @@ export class Tabs implements NavOutlet {
|
||||
|
||||
private initTabs() {
|
||||
const tabs = this.tabs = Array.from(this.el.querySelectorAll('ion-tab'));
|
||||
const tabPromises: Promise<any>[] = [];
|
||||
for (const tab of tabs) {
|
||||
const id = `t-${this.tabsId}-${++this.ids}`;
|
||||
tab.btnId = 'tab-' + id;
|
||||
tab.id = 'tabpanel-' + id;
|
||||
tabPromises.push((tab as any).componentOnReady());
|
||||
}
|
||||
return Promise.all(tabPromises);
|
||||
}
|
||||
|
||||
private initSelect() {
|
||||
if (document.querySelector('ion-router')) {
|
||||
return;
|
||||
return Promise.resolve();
|
||||
}
|
||||
// find pre-selected tabs
|
||||
const selectedTab = this.tabs.find(t => t.selected) ||
|
||||
@ -192,10 +202,10 @@ export class Tabs implements NavOutlet {
|
||||
tab.selected = false;
|
||||
}
|
||||
}
|
||||
if (selectedTab) {
|
||||
selectedTab.setActive(true);
|
||||
}
|
||||
this.selectedTab = selectedTab;
|
||||
const promise = selectedTab ? selectedTab.setActive(true) : Promise.resolve();
|
||||
return promise.then(() => {
|
||||
this.selectedTab = selectedTab;
|
||||
});
|
||||
}
|
||||
|
||||
private loadConfig(attrKey: string, fallback: any) {
|
||||
|
5
packages/core/src/index.d.ts
vendored
5
packages/core/src/index.d.ts
vendored
@ -146,6 +146,11 @@ export interface FrameworkDelegate {
|
||||
removeViewFromDom(elementOrContainerToUnmountFrom: any, elementOrComponentToUnmount: any, escapeHatch?: any): Promise<void>;
|
||||
}
|
||||
|
||||
export interface RouterDelegate {
|
||||
pushUrlState(urlSegment: string, stateObject?: any, title?: string): Promise<any>;
|
||||
popUrlState(): Promise<any>;
|
||||
}
|
||||
|
||||
export interface FrameworkMountingData {
|
||||
element: HTMLElement;
|
||||
component: any;
|
||||
|
@ -28,12 +28,4 @@ export class DomFrameworkDelegate implements FrameworkDelegate {
|
||||
parentElement.removeChild(childElement);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
shouldDeferToRouter(_elementOrComponentToMount: any): Promise<boolean> {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
|
||||
routeToUrl(_elementOrComponentToMount: any): Promise<any> {
|
||||
return Promise.resolve('todo');
|
||||
}
|
||||
}
|
||||
|
16
packages/core/src/utils/dom-router-delegate.ts
Normal file
16
packages/core/src/utils/dom-router-delegate.ts
Normal file
@ -0,0 +1,16 @@
|
||||
|
||||
|
||||
import { RouterDelegate } from '../index';
|
||||
|
||||
export class DomRouterDelegate implements RouterDelegate {
|
||||
|
||||
pushUrlState(urlSegment: string, stateObject: any = null, title = ''): Promise<any> {
|
||||
history.pushState(stateObject, title, urlSegment);
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
popUrlState() {
|
||||
history.back();
|
||||
return Promise.resolve();
|
||||
}
|
||||
}
|
@ -303,3 +303,16 @@ export function getNavAsChildIfExists(element: HTMLElement): HTMLIonNavElement|n
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function normalizeUrl(url: string) {
|
||||
url = url.trim();
|
||||
if (url.charAt(0) !== '/') {
|
||||
// ensure first char is a /
|
||||
url = '/' + url;
|
||||
}
|
||||
if (url.length > 1 && url.charAt(url.length - 1) === '/') {
|
||||
// ensure last char is not a /
|
||||
url = url.substr(0, url.length - 1);
|
||||
}
|
||||
return url;
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"allowUnreachableCode": false,
|
||||
"alwaysStrict": true,
|
||||
"declaration": true,
|
||||
"experimentalDecorators": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "react",
|
||||
|
@ -14,12 +14,15 @@ const routes: Routes = [
|
||||
{ path: 'content', loadChildren: 'app/content/content.module#ContentModule' },
|
||||
{ path: 'toast', loadChildren: 'app/toast/toast.module#ToastModule' },
|
||||
{ path: 'loading', loadChildren: 'app/loading/loading.module#LoadingModule' },
|
||||
{ path: 'no-routing-nav', loadChildren: 'app/no-routing-nav/no-routing-nav.module#NoRoutingNavModule' },
|
||||
{ path: 'modal', loadChildren: 'app/modal/modal.module#ModalModule' },
|
||||
{ path: 'popover', loadChildren: 'app/popover/popover.module#PopoverModule' },
|
||||
{ path: 'segment', loadChildren: 'app/segment/segment.module#SegmentModule' },
|
||||
{ path: 'virtual-scroll', loadChildren: 'app/virtual-scroll/virtual-scroll.module#VirtualScrollModule' },
|
||||
|
||||
{ path: 'no-routing-nav', loadChildren: 'app/no-routing-nav/no-routing-nav.module#NoRoutingNavModule' },
|
||||
{ path: 'simple-nav', loadChildren: 'app/simple-nav/simple-nav.module#SimpleNavModule' },
|
||||
{ path: 'nested-nav', loadChildren: 'app/nested-nav/nested-nav.module#NestedNavModule' },
|
||||
{ path: 'nav-then-tabs', loadChildren: 'app/nav-then-tabs/nav-then-tabs.module#NavThenTabsModule' },
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
|
@ -51,5 +51,19 @@
|
||||
|
||||
<div>
|
||||
<h2>Nav Tests</h2>
|
||||
<a href='no-routing-nav'>No Routing</a>
|
||||
<ul>
|
||||
<li>
|
||||
<a href='no-routing-nav'>No Routing</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='simple-nav/page-one'>Simple Nav</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='nested-nav/nested-page-one'>Nested Nav</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href='nav-then-tabs/login'>Nav Then Tabs</a>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
</div>
|
||||
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { LoginPage } from './login';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: LoginPage}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class LoginRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { LoginPage } from './login';
|
||||
import { LoginRoutingModule } from './login-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
LoginRoutingModule
|
||||
],
|
||||
declarations: [LoginPage],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class LoginModule { }
|
38
packages/demos/angular/src/app/nav-then-tabs/login/login.ts
Normal file
38
packages/demos/angular/src/app/nav-then-tabs/login/login.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'login',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Login Page</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Login - {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageTwoComponent()">Login to app</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class LoginPage {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
pushPageTwoComponent() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-one:one)');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { NavThenTabsPageComponent } from './nav-then-tabs.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: NavThenTabsPageComponent,
|
||||
children: [
|
||||
{ path: 'login', loadChildren: './login/login.module#LoginModule' },
|
||||
{ path: 'app', loadChildren: './tabs-page/tabs-page.module#TabsPageModule' }
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class NavThenTabsRoutingModule { }
|
@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-nav></ion-nav>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class NavThenTabsPageComponent {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
|
||||
import { NavThenTabsPageComponent } from './nav-then-tabs.component';
|
||||
import { NavThenTabsRoutingModule } from './nav-then-tabs-routing.module';
|
||||
|
||||
import { IonicAngularModule, IonicRouterModule } from '@ionic/angular';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
NavThenTabsPageComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule,
|
||||
NavThenTabsRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class NavThenTabsModule {}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabOnePageOne } from './tab-one-page-one';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabOnePageOne}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabOnePageOneRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabOnePageOne } from './tab-one-page-one';
|
||||
import { TabOnePageOneRoutingModule } from './tab-one-page-one-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabOnePageOneRoutingModule
|
||||
],
|
||||
declarations: [TabOnePageOne],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabOnePageOneModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-one-page-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab One Page One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab One Page One {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabOnePageOne {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-one:two)');
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabOnePageThree } from './tab-one-page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabOnePageThree}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabOnePageThreeRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabOnePageThree } from './tab-one-page-three';
|
||||
import { TabOnePageThreeRoutingModule } from './tab-one-page-three-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabOnePageThreeRoutingModule
|
||||
],
|
||||
declarations: [TabOnePageThree],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabOnePageThreeModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-one-page-three',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab One Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab One Page Three {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabOnePageThree {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabOnePageTwo } from './tab-one-page-two';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabOnePageTwo}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabOnePageTwoRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabOnePageTwo } from './tab-one-page-two';
|
||||
import { TabOnePageTwoRoutingModule } from './tab-one-page-two-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabOnePageTwoRoutingModule
|
||||
],
|
||||
declarations: [TabOnePageTwo],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabOnePageTwoModule { }
|
@ -0,0 +1,41 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-one-page-two',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab One Page Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab One Page Two {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Three</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabOnePageTwo {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-one:three)');
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabThreePageOne } from './tab-three-page-one';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabThreePageOne}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabThreePageOneRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabThreePageOne } from './tab-three-page-one';
|
||||
import { TabThreePageOneRoutingModule } from './tab-three-page-one-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabThreePageOneRoutingModule
|
||||
],
|
||||
declarations: [TabThreePageOne],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabThreePageOneModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-three-page-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Three Page One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Three Page One {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabThreePageOne {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-three:two)');
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabThreePageThree } from './tab-three-page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabThreePageThree}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabThreePageThreeRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabThreePageThree } from './tab-three-page-three';
|
||||
import { TabThreePageThreeRoutingModule } from './tab-three-page-three-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabThreePageThreeRoutingModule
|
||||
],
|
||||
declarations: [TabThreePageThree],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabThreePageThreeModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-three-page-three',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Three Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Three Page Three {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabThreePageThree {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabThreePageTwo } from './tab-three-page-two';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabThreePageTwo}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabThreePageTwoRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabThreePageTwo } from './tab-three-page-two';
|
||||
import { TabThreePageTwoRoutingModule } from './tab-three-page-two-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabThreePageTwoRoutingModule
|
||||
],
|
||||
declarations: [TabThreePageTwo],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabThreePageTwoModule { }
|
@ -0,0 +1,41 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-three-page-two',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Three Page Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Three Page Two {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Three</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabThreePageTwo {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-three:three)');
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabTwoPageOne } from './tab-two-page-one';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabTwoPageOne}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabTwoPageOneRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabTwoPageOne } from './tab-two-page-one';
|
||||
import { TabTwoPageOneRoutingModule } from './tab-two-page-one-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabTwoPageOneRoutingModule
|
||||
],
|
||||
declarations: [TabTwoPageOne],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabTwoPageOneModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-two-page-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Two Page One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Two Page One {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabTwoPageOne {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-two:two)');
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabTwoPageThree } from './tab-two-page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabTwoPageThree}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabTwoPageThreeRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabTwoPageThree } from './tab-two-page-three';
|
||||
import { TabTwoPageThreeRoutingModule } from './tab-two-page-three-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabTwoPageThreeRoutingModule
|
||||
],
|
||||
declarations: [TabTwoPageThree],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabTwoPageThreeModule { }
|
@ -0,0 +1,34 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-two-page-three',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Two Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Two Page Three {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabTwoPageThree {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabTwoPageTwo } from './tab-two-page-two';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: TabTwoPageTwo}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabTwoPageTwoRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { TabTwoPageTwo } from './tab-two-page-two';
|
||||
import { TabTwoPageTwoRoutingModule } from './tab-two-page-two-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabTwoPageTwoRoutingModule
|
||||
],
|
||||
declarations: [TabTwoPageTwo],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabTwoPageTwoModule { }
|
@ -0,0 +1,41 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tab-two-page-two',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Tab Two Page Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Tab Two Page Two {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="next()">Go to Page Three</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="back()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class TabTwoPageTwo {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
next() {
|
||||
this.navController.push('/nav-then-tabs/app/tabs/(tab-two:three)');
|
||||
}
|
||||
|
||||
back() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { TabsPage } from './tabs-page';
|
||||
|
||||
import { TabOnePageOne } from '../tab-one-page-one/tab-one-page-one';
|
||||
import { TabOnePageTwo } from '../tab-one-page-two/tab-one-page-two';
|
||||
import { TabOnePageThree } from '../tab-one-page-three/tab-one-page-three';
|
||||
|
||||
import { TabTwoPageOne } from '../tab-two-page-one/tab-two-page-one';
|
||||
import { TabTwoPageTwo } from '../tab-two-page-two/tab-two-page-two';
|
||||
import { TabTwoPageThree } from '../tab-two-page-three/tab-two-page-three';
|
||||
|
||||
import { TabThreePageOne } from '../tab-three-page-one/tab-three-page-one';
|
||||
import { TabThreePageTwo } from '../tab-three-page-two/tab-three-page-two';
|
||||
import { TabThreePageThree } from '../tab-three-page-three/tab-three-page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: 'tabs',
|
||||
component: TabsPage,
|
||||
children: [
|
||||
{
|
||||
path: 'one',
|
||||
component: TabOnePageOne,
|
||||
outlet: 'tab-one'
|
||||
},
|
||||
{
|
||||
path: 'two',
|
||||
component: TabOnePageTwo,
|
||||
outlet: 'tab-one'
|
||||
},
|
||||
{
|
||||
path: 'three',
|
||||
component: TabOnePageThree,
|
||||
outlet: 'tab-one'
|
||||
},
|
||||
{
|
||||
path: 'one',
|
||||
component: TabTwoPageOne,
|
||||
outlet: 'tab-two'
|
||||
},
|
||||
{
|
||||
path: 'two',
|
||||
component: TabTwoPageTwo,
|
||||
outlet: 'tab-two'
|
||||
},
|
||||
{
|
||||
path: 'three',
|
||||
component: TabTwoPageThree,
|
||||
outlet: 'tab-two'
|
||||
},
|
||||
{
|
||||
path: 'one',
|
||||
component: TabThreePageOne,
|
||||
outlet: 'tab-three'
|
||||
},
|
||||
{
|
||||
path: 'two',
|
||||
component: TabThreePageTwo,
|
||||
outlet: 'tab-three'
|
||||
},
|
||||
{
|
||||
path: 'three',
|
||||
component: TabThreePageThree,
|
||||
outlet: 'tab-three'
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TabsPageRoutingModule { }
|
@ -0,0 +1,52 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
IonicAngularModule,
|
||||
IonicRouterModule
|
||||
} from '@ionic/angular';
|
||||
|
||||
import { TabsPage } from './tabs-page';
|
||||
|
||||
import { TabsPageRoutingModule } from './tabs-page-routing.module';
|
||||
|
||||
import { TabOnePageOneModule } from '../tab-one-page-one/tab-one-page-one.module';
|
||||
import { TabOnePageTwoModule } from '../tab-one-page-two/tab-one-page-two.module';
|
||||
import { TabOnePageThreeModule } from '../tab-one-page-three/tab-one-page-three.module';
|
||||
|
||||
import { TabTwoPageOneModule } from '../tab-two-page-one/tab-two-page-one.module';
|
||||
import { TabTwoPageTwoModule } from '../tab-two-page-two/tab-two-page-two.module';
|
||||
import { TabTwoPageThreeModule } from '../tab-two-page-three/tab-two-page-three.module';
|
||||
|
||||
import { TabThreePageOneModule } from '../tab-three-page-one/tab-three-page-one.module';
|
||||
import { TabThreePageTwoModule } from '../tab-three-page-two/tab-three-page-two.module';
|
||||
import { TabThreePageThreeModule } from '../tab-three-page-three/tab-three-page-three.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
TabsPageRoutingModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule,
|
||||
TabOnePageOneModule,
|
||||
TabOnePageTwoModule,
|
||||
TabOnePageThreeModule,
|
||||
|
||||
|
||||
TabTwoPageOneModule,
|
||||
TabTwoPageTwoModule,
|
||||
TabTwoPageThreeModule,
|
||||
|
||||
|
||||
TabThreePageOneModule,
|
||||
TabThreePageTwoModule,
|
||||
TabThreePageThreeModule
|
||||
],
|
||||
declarations: [
|
||||
TabsPage,
|
||||
],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class TabsPageModule { }
|
@ -0,0 +1,38 @@
|
||||
import { Component, ElementRef, ViewChild, ViewEncapsulation } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'tabs-page',
|
||||
template: `
|
||||
<ion-tabs>
|
||||
<ion-tab title="Tab One" icon="star" #tabOne>
|
||||
<ion-nav [root]="tabOnePageOne" name="tab-one" lazy="true"></ion-nav>
|
||||
</ion-tab>
|
||||
<ion-tab title="Tab Two" icon="globe" #tabTwo>
|
||||
<ion-nav [root]="tabTwoPageOne" name="tab-two" lazy="true"></ion-nav>
|
||||
</ion-tab>
|
||||
<ion-tab title="Tab Three" icon="logo-facebook" #tabThree>
|
||||
<ion-nav [root]="tabThreePageOne" name="tab-three" lazy="true"></ion-nav>
|
||||
</ion-tab>
|
||||
</ion-tabs>
|
||||
`
|
||||
})
|
||||
export class TabsPage {
|
||||
|
||||
tabOnePageOne = '/nav-then-tabs/app/tabs/(tab-one:one)';
|
||||
tabTwoPageOne = '/nav-then-tabs/app/tabs/(tab-two:one)';
|
||||
tabThreePageOne = '/nav-then-tabs/app/tabs/(tab-three:one)';
|
||||
|
||||
@ViewChild('tabOne') tabOne: ElementRef;
|
||||
@ViewChild('tabTwo') tabTwo: ElementRef;
|
||||
@ViewChild('tabThree') tabThree: ElementRef;
|
||||
|
||||
constructor(private router: Router, private location: Location) {
|
||||
}
|
||||
|
||||
goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { NestedNavPageComponent } from './nested-nav.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: NestedNavPageComponent,
|
||||
children: [
|
||||
{ path: 'nested-page-one', loadChildren: './nested-page-one/page-one.module#PageOneModule' },
|
||||
{ path: 'nested-page-two', loadChildren: './nested-page-two/page-two.module#PageTwoModule' },
|
||||
{ path: 'nested-page-three', loadChildren: './nested-page-three/page-three.module#PageThreeModule' }
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class NestedNavRoutingModule { }
|
@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-nav></ion-nav>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class NestedNavPageComponent {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
|
||||
import { NestedNavPageComponent } from './nested-nav.component';
|
||||
import { NestedNavRoutingModule } from './nested-nav-routing.module';
|
||||
|
||||
import { IonicAngularModule, IonicRouterModule } from '@ionic/angular';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
NestedNavPageComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule,
|
||||
NestedNavRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class NestedNavModule {}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageOne } from './page-one';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: PageOne}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageOneRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PageOne } from './page-one';
|
||||
import { PageOneRoutingModule } from './page-one-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageOneRoutingModule
|
||||
],
|
||||
declarations: [PageOne],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageOneModule { }
|
@ -0,0 +1,36 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'page-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Nested Page One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page One - {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageTwoComponent()">Go to Page Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageOne {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
pushPageTwoComponent() {
|
||||
this.navController.push('/nested-nav/nested-page-two/section-one');
|
||||
}
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageThree } from './page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: PageThree }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageThreeRoutingModule { }
|
@ -0,0 +1,19 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PageThree } from './page-three';
|
||||
import { PageThreeRoutingModule } from './page-three-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageThreeRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
PageThree
|
||||
],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageThreeModule { }
|
@ -0,0 +1,39 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'page-three',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page Three {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="navPop()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageThree {
|
||||
|
||||
ts: number;
|
||||
constructor(private router: Router, private location: Location) {
|
||||
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
navPop() {
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,29 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageTwo } from './page-two';
|
||||
import { PageTwoSectionOne } from './page-two-section-one';
|
||||
import { PageTwoSectionTwo } from './page-two-section-two';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PageTwo,
|
||||
children: [
|
||||
{
|
||||
path: 'section-one',
|
||||
component: PageTwoSectionOne,
|
||||
},
|
||||
{
|
||||
path: 'section-two',
|
||||
component: PageTwoSectionTwo,
|
||||
}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageTwoRoutingModule { }
|
@ -0,0 +1,43 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'page-two-section-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Page Two Section One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page Two Section One - TS {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageTwoComponent()">Go to Section Two</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="goBack()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageTwoSectionOne {
|
||||
|
||||
ts: number;
|
||||
|
||||
constructor(private router: Router) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
pushPageTwoComponent() {
|
||||
this.router.navigateByUrl('/nested-nav/nested-page-two/section-two');
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.router.navigateByUrl('/nested-nav/nested-page-one');
|
||||
}
|
||||
}
|
@ -0,0 +1,42 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Router } from '@angular/router';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'page-two-section-two',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Page Two Section Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page Two Section Two {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageTwoComponent()">Go to Page Three</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="goBack()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageTwoSectionTwo {
|
||||
|
||||
ts: number;
|
||||
constructor(private router: Router) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
pushPageTwoComponent() {
|
||||
this.router.navigateByUrl('/nested-nav/nested-page-three');
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.router.navigateByUrl('/nested-nav/nested-page-two/section-one');
|
||||
}
|
||||
}
|
@ -0,0 +1,32 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
IonicAngularModule,
|
||||
IonicRouterModule
|
||||
} from '@ionic/angular';
|
||||
|
||||
import { PageTwo } from './page-two';
|
||||
import { PageTwoSectionOne } from './page-two-section-one';
|
||||
import { PageTwoSectionTwo } from './page-two-section-two';
|
||||
|
||||
import { PageTwoRoutingModule } from './page-two-routing.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageTwoRoutingModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule
|
||||
],
|
||||
declarations: [
|
||||
PageTwo,
|
||||
PageTwoSectionOne,
|
||||
PageTwoSectionTwo
|
||||
],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageTwoModule { }
|
@ -0,0 +1,24 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'page-two',
|
||||
template: `
|
||||
<ion-nav></ion-nav>
|
||||
<!-- <router-outlet></router-outlet> -->
|
||||
`
|
||||
})
|
||||
export class PageTwo {
|
||||
|
||||
constructor(private navController: NavController) {
|
||||
}
|
||||
|
||||
pushPageThree() {
|
||||
this.navController.push('/nested-nav/nested-page-three');
|
||||
}
|
||||
|
||||
goBack() {
|
||||
window.history.back();
|
||||
}
|
||||
}
|
@ -6,6 +6,9 @@ import { Component } from '@angular/core';
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
@ -8,6 +8,9 @@ import { PageThree } from './page-three';
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
<ion-back-button></ion-back-button>
|
||||
</ion-buttons>
|
||||
<ion-title>Page Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageOne } from './page-one';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: PageOne}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageOneRoutingModule { }
|
@ -0,0 +1,17 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PageOne } from './page-one';
|
||||
import { PageOneRoutingModule } from './page-one-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageOneRoutingModule
|
||||
],
|
||||
declarations: [PageOne],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageOneModule { }
|
@ -0,0 +1,40 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
import { PageTwo } from '../page-two/page-two';
|
||||
|
||||
@Component({
|
||||
selector: 'page-one',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Simple Page One</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page One - {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageTwoComponent()">Go to Page Two</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageOne {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
pushPageTwoComponent() {
|
||||
this.navController.push('/simple-nav/page-two');
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
@ -0,0 +1,14 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageThree } from './page-three';
|
||||
|
||||
const routes: Routes = [
|
||||
{ path: '', component: PageThree }
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageThreeRoutingModule { }
|
@ -0,0 +1,19 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import { PageThree } from './page-three';
|
||||
import { PageThreeRoutingModule } from './page-three-routing.module';
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageThreeRoutingModule
|
||||
],
|
||||
declarations: [
|
||||
PageThree
|
||||
],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageThreeModule { }
|
@ -0,0 +1,37 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
@Component({
|
||||
selector: 'page-three',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Page Three</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page Three {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="navPop()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageThree {
|
||||
|
||||
ts: number;
|
||||
constructor(private navController: NavController) {
|
||||
|
||||
setInterval(() => {
|
||||
this.ts = Date.now();
|
||||
}, 500);
|
||||
}
|
||||
|
||||
|
||||
navPop() {
|
||||
this.navController.pop();
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { PageTwo } from './page-two';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: PageTwo,
|
||||
}
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class PageTwoRoutingModule { }
|
@ -0,0 +1,27 @@
|
||||
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';
|
||||
import { CommonModule } from '@angular/common';
|
||||
|
||||
import {
|
||||
IonicAngularModule,
|
||||
IonicRouterModule
|
||||
} from '@ionic/angular';
|
||||
|
||||
import { PageTwo } from './page-two';
|
||||
import { PageTwoRoutingModule } from './page-two-routing.module';
|
||||
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
PageTwoRoutingModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule
|
||||
],
|
||||
declarations: [
|
||||
PageTwo,
|
||||
],
|
||||
schemas: [
|
||||
CUSTOM_ELEMENTS_SCHEMA
|
||||
]
|
||||
})
|
||||
export class PageTwoModule { }
|
@ -0,0 +1,39 @@
|
||||
import { Component, ViewEncapsulation } from '@angular/core';
|
||||
import { Location } from '@angular/common';
|
||||
import { NavController } from '@ionic/angular';
|
||||
|
||||
|
||||
@Component({
|
||||
selector: 'page-two',
|
||||
template: `
|
||||
<ion-page>
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-title>Page Two</ion-title>
|
||||
</ion-toolbar>
|
||||
</ion-header>
|
||||
<ion-content padding>
|
||||
Page Two - {{ts}}
|
||||
<div>
|
||||
<ion-button (click)="pushPageThreeComponent()">Go to Page Three</ion-button>
|
||||
</div>
|
||||
<div>
|
||||
<ion-button (click)="goBack()">Go Back</ion-button>
|
||||
</div>
|
||||
</ion-content>
|
||||
</ion-page>
|
||||
`
|
||||
})
|
||||
export class PageTwo {
|
||||
|
||||
constructor(private navController: NavController) {
|
||||
}
|
||||
|
||||
pushPageThreeComponent() {
|
||||
this.navController.push('/simple-nav/page-three');
|
||||
}
|
||||
|
||||
goBack() {
|
||||
this.navController.pop();
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
import { NgModule } from '@angular/core';
|
||||
import { Routes, RouterModule } from '@angular/router';
|
||||
|
||||
import { SimpleNavPageComponent } from './simple-nav.component';
|
||||
|
||||
const routes: Routes = [
|
||||
{
|
||||
path: '',
|
||||
component: SimpleNavPageComponent,
|
||||
children: [
|
||||
{ path: 'page-one', loadChildren: './page-one/page-one.module#PageOneModule' },
|
||||
{ path: 'page-two', loadChildren: './page-two/page-two.module#PageTwoModule' },
|
||||
{ path: 'page-three', loadChildren: './page-three/page-three.module#PageThreeModule' }
|
||||
]
|
||||
},
|
||||
];
|
||||
|
||||
@NgModule({
|
||||
imports: [RouterModule.forChild(routes)],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class SimpleNavRoutingModule { }
|
@ -0,0 +1,15 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-nav-page',
|
||||
template: `
|
||||
<ion-app>
|
||||
<ion-nav></ion-nav>
|
||||
</ion-app>
|
||||
`
|
||||
})
|
||||
export class SimpleNavPageComponent {
|
||||
constructor() {
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
import { CommonModule } from '@angular/common';
|
||||
import { CUSTOM_ELEMENTS_SCHEMA, NgModule } from '@angular/core';
|
||||
|
||||
import { SimpleNavPageComponent } from './simple-nav.component';
|
||||
import { SimpleNavRoutingModule } from './simple-nav-routing.module';
|
||||
|
||||
import { IonicAngularModule, IonicRouterModule } from '@ionic/angular';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
SimpleNavPageComponent,
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
IonicAngularModule,
|
||||
IonicRouterModule,
|
||||
SimpleNavRoutingModule
|
||||
],
|
||||
schemas: [CUSTOM_ELEMENTS_SCHEMA]
|
||||
})
|
||||
export class SimpleNavModule {}
|
Reference in New Issue
Block a user