mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-21 04:53:58 +08:00
feat(app): getActiveNav() method
This commit is contained in:
@ -1,9 +1,10 @@
|
|||||||
import {Injectable, NgZone} from 'angular2/core';
|
import {Injectable} from 'angular2/core';
|
||||||
import {Title} from 'angular2/platform/browser';
|
import {Title} from 'angular2/platform/browser';
|
||||||
|
|
||||||
import {Config} from '../../config/config';
|
import {Config} from '../../config/config';
|
||||||
import {ClickBlock} from '../../util/click-block';
|
import {ClickBlock} from '../../util/click-block';
|
||||||
import {rafFrames} from '../../util/dom';
|
import {Nav} from '../nav/nav';
|
||||||
|
import {Tabs} from '../tabs/tabs';
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -18,11 +19,11 @@ export class IonicApp {
|
|||||||
private _title: string = '';
|
private _title: string = '';
|
||||||
private _titleSrv: Title = new Title();
|
private _titleSrv: Title = new Title();
|
||||||
private _isProd: boolean = false;
|
private _isProd: boolean = false;
|
||||||
|
private _rootNav: any = null;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
private _config: Config,
|
private _config: Config,
|
||||||
private _clickBlock: ClickBlock,
|
private _clickBlock: ClickBlock
|
||||||
private _zone: NgZone
|
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -98,6 +99,38 @@ export class IonicApp {
|
|||||||
return (this._scrollTime + 64 > Date.now());
|
return (this._scrollTime + 64 > Date.now());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getActiveNav(): Nav | Tabs {
|
||||||
|
var nav = this._rootNav || null;
|
||||||
|
var activeChildNav;
|
||||||
|
|
||||||
|
while (nav) {
|
||||||
|
activeChildNav = nav.getActiveChildNav();
|
||||||
|
if (!activeChildNav) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
nav = activeChildNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nav;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getRootNav(): any {
|
||||||
|
return this._rootNav;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
setRootNav(nav: any) {
|
||||||
|
this._rootNav = nav;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
* Register a known component with a key, for easy lookups later.
|
* Register a known component with a key, for easy lookups later.
|
||||||
|
112
ionic/components/app/test/app.spec.ts
Normal file
112
ionic/components/app/test/app.spec.ts
Normal file
@ -0,0 +1,112 @@
|
|||||||
|
import {IonicApp, Nav, Tabs, Tab, NavOptions, Config, ViewController} from '../../../../ionic';
|
||||||
|
|
||||||
|
export function run() {
|
||||||
|
|
||||||
|
|
||||||
|
describe('IonicApp', () => {
|
||||||
|
|
||||||
|
describe('getActiveNav', () => {
|
||||||
|
|
||||||
|
it('should get active NavController when using tabs with nested nav', () => {
|
||||||
|
let nav = mockNav();
|
||||||
|
app.setRootNav(nav);
|
||||||
|
|
||||||
|
let tabs = mockTabs();
|
||||||
|
let tab1 = mockTab(tabs);
|
||||||
|
let tab2 = mockTab(tabs);
|
||||||
|
nav.registerChildNav(tabs);
|
||||||
|
|
||||||
|
tab2.setSelected(true);
|
||||||
|
let nav2 = mockNav();
|
||||||
|
let nav3 = mockNav();
|
||||||
|
let nav4 = mockNav();
|
||||||
|
tab1.registerChildNav(nav4);
|
||||||
|
tab2.registerChildNav(nav2);
|
||||||
|
tab2.registerChildNav(nav3);
|
||||||
|
|
||||||
|
expect(app.getActiveNav()).toBe(nav3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get active NavController when using tabs', () => {
|
||||||
|
let nav = mockNav();
|
||||||
|
app.setRootNav(nav);
|
||||||
|
|
||||||
|
let tabs = mockTabs();
|
||||||
|
let tab1 = mockTab(tabs);
|
||||||
|
let tab2 = mockTab(tabs);
|
||||||
|
let tab3 = mockTab(tabs);
|
||||||
|
nav.registerChildNav(tabs);
|
||||||
|
|
||||||
|
tab2.setSelected(true);
|
||||||
|
|
||||||
|
expect(app.getActiveNav()).toBe(tab2);
|
||||||
|
|
||||||
|
tab2.setSelected(false);
|
||||||
|
tab3.setSelected(true);
|
||||||
|
expect(app.getActiveNav()).toBe(tab3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get active NavController when nested 3 deep', () => {
|
||||||
|
let nav1 = mockNav();
|
||||||
|
let nav2 = mockNav();
|
||||||
|
let nav3 = mockNav();
|
||||||
|
app.setRootNav(nav1);
|
||||||
|
|
||||||
|
nav1.registerChildNav(nav2);
|
||||||
|
nav2.registerChildNav(nav3);
|
||||||
|
|
||||||
|
expect(app.getActiveNav()).toBe(nav3);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get active NavController when nested 2 deep', () => {
|
||||||
|
let nav1 = mockNav();
|
||||||
|
let nav2 = mockNav();
|
||||||
|
app.setRootNav(nav1);
|
||||||
|
|
||||||
|
nav1.registerChildNav(nav2);
|
||||||
|
expect(app.getActiveNav()).toBe(nav2);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should get active NavController when only one nav controller', () => {
|
||||||
|
let nav = mockNav();
|
||||||
|
app.setRootNav(nav);
|
||||||
|
expect(app.getActiveNav()).toBe(nav);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should set/get the root nav controller', () => {
|
||||||
|
let nav = mockNav();
|
||||||
|
app.setRootNav(nav);
|
||||||
|
expect(app.getRootNav()).toBe(nav);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not get an active NavController if there is not root set', () => {
|
||||||
|
expect(app.getActiveNav()).toBeNull();
|
||||||
|
expect(app.getRootNav()).toBeNull();
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
var app: IonicApp;
|
||||||
|
var config: Config;
|
||||||
|
|
||||||
|
function mockNav(): Nav {
|
||||||
|
return new Nav(null,null,null,config,null,null,null,null,null,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockTabs(): Tabs {
|
||||||
|
return new Tabs(null, null, null, config, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
function mockTab(parentTabs: Tabs): Tab {
|
||||||
|
return new Tab(parentTabs,null,config,null,null,null,null,null,null);
|
||||||
|
}
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
config = new Config();
|
||||||
|
app = new IonicApp(config, null);
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -110,6 +110,7 @@ export class NavController extends Ion {
|
|||||||
private _sbGesture: SwipeBackGesture;
|
private _sbGesture: SwipeBackGesture;
|
||||||
private _sbThreshold: number;
|
private _sbThreshold: number;
|
||||||
private _portal: Portal;
|
private _portal: Portal;
|
||||||
|
private _children: any[] = [];
|
||||||
|
|
||||||
protected _sbEnabled: boolean;
|
protected _sbEnabled: boolean;
|
||||||
protected _ids: number = -1;
|
protected _ids: number = -1;
|
||||||
@ -166,8 +167,8 @@ export class NavController extends Ion {
|
|||||||
|
|
||||||
this._trnsDelay = config.get('pageTransitionDelay');
|
this._trnsDelay = config.get('pageTransitionDelay');
|
||||||
|
|
||||||
this._sbEnabled = config.getBoolean('swipeBackEnabled') || false;
|
this._sbEnabled = config.getBoolean('swipeBackEnabled');
|
||||||
this._sbThreshold = config.get('swipeBackThreshold') || 40;
|
this._sbThreshold = config.getNumber('swipeBackThreshold', 40);
|
||||||
|
|
||||||
this.id = (++ctrlIds).toString();
|
this.id = (++ctrlIds).toString();
|
||||||
|
|
||||||
@ -1322,6 +1323,21 @@ export class NavController extends Ion {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getActiveChildNav(): any {
|
||||||
|
return this._children[this._children.length - 1];
|
||||||
|
}
|
||||||
|
|
||||||
|
registerChildNav(nav: any) {
|
||||||
|
this._children.push(nav);
|
||||||
|
}
|
||||||
|
|
||||||
|
unregisterChildNav(nav: any) {
|
||||||
|
let index = this._children.indexOf(nav);
|
||||||
|
if (index > -1) {
|
||||||
|
this._children.splice(index, 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
@ -1329,7 +1345,11 @@ export class NavController extends Ion {
|
|||||||
for (var i = this._views.length - 1; i >= 0; i--) {
|
for (var i = this._views.length - 1; i >= 0; i--) {
|
||||||
this._views[i].destroy();
|
this._views[i].destroy();
|
||||||
}
|
}
|
||||||
this._views = [];
|
this._views.length = 0;
|
||||||
|
|
||||||
|
if (this.parent) {
|
||||||
|
this.parent.unregisterChildNav(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -113,7 +113,7 @@ export class Nav extends NavController {
|
|||||||
private _hasInit: boolean = false;
|
private _hasInit: boolean = false;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Optional() hostNavCtrl: NavController,
|
@Optional() parent: NavController,
|
||||||
@Optional() viewCtrl: ViewController,
|
@Optional() viewCtrl: ViewController,
|
||||||
app: IonicApp,
|
app: IonicApp,
|
||||||
config: Config,
|
config: Config,
|
||||||
@ -124,7 +124,7 @@ export class Nav extends NavController {
|
|||||||
zone: NgZone,
|
zone: NgZone,
|
||||||
renderer: Renderer
|
renderer: Renderer
|
||||||
) {
|
) {
|
||||||
super(hostNavCtrl, app, config, keyboard, elementRef, 'contents', compiler, viewManager, zone, renderer);
|
super(parent, app, config, keyboard, elementRef, 'contents', compiler, viewManager, zone, renderer);
|
||||||
|
|
||||||
if (viewCtrl) {
|
if (viewCtrl) {
|
||||||
// an ion-nav can also act as an ion-page within a parent ion-nav
|
// an ion-nav can also act as an ion-page within a parent ion-nav
|
||||||
@ -132,6 +132,15 @@ export class Nav extends NavController {
|
|||||||
viewCtrl.setContent(this);
|
viewCtrl.setContent(this);
|
||||||
viewCtrl.setContentRef(elementRef);
|
viewCtrl.setContentRef(elementRef);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
// this Nav has a parent Nav
|
||||||
|
parent.registerChildNav(this);
|
||||||
|
|
||||||
|
} else if (app) {
|
||||||
|
// this is the root navcontroller for the entire app
|
||||||
|
this._app.setRootNav(this);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +92,7 @@ export class Tab extends NavController {
|
|||||||
private _panelId: string;
|
private _panelId: string;
|
||||||
private _btnId: string;
|
private _btnId: string;
|
||||||
private _loaded: boolean;
|
private _loaded: boolean;
|
||||||
private _loadTmr: number;
|
private _loadTmr: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
|
@ -135,8 +135,8 @@ export class Tabs extends Ion {
|
|||||||
parent: any;
|
parent: any;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@Optional() viewCtrl: ViewController,
|
|
||||||
@Optional() parent: NavController,
|
@Optional() parent: NavController,
|
||||||
|
@Optional() viewCtrl: ViewController,
|
||||||
private _app: IonicApp,
|
private _app: IonicApp,
|
||||||
private _config: Config,
|
private _config: Config,
|
||||||
private _elementRef: ElementRef,
|
private _elementRef: ElementRef,
|
||||||
@ -149,6 +149,15 @@ export class Tabs extends Ion {
|
|||||||
this.subPages = _config.getBoolean('tabSubPages');
|
this.subPages = _config.getBoolean('tabSubPages');
|
||||||
this._useHighlight = _config.getBoolean('tabbarHighlight');
|
this._useHighlight = _config.getBoolean('tabbarHighlight');
|
||||||
|
|
||||||
|
if (parent) {
|
||||||
|
// this Tabs has a parent Nav
|
||||||
|
parent.registerChildNav(this);
|
||||||
|
|
||||||
|
} else if (this._app) {
|
||||||
|
// this is the root navcontroller for the entire app
|
||||||
|
this._app.setRootNav(this);
|
||||||
|
}
|
||||||
|
|
||||||
// Tabs may also be an actual ViewController which was navigated to
|
// Tabs may also be an actual ViewController which was navigated to
|
||||||
// if Tabs is static and not navigated to within a NavController
|
// if Tabs is static and not navigated to within a NavController
|
||||||
// then skip this and don't treat it as it's own ViewController
|
// then skip this and don't treat it as it's own ViewController
|
||||||
@ -308,6 +317,13 @@ export class Tabs extends Ion {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
getActiveChildNav() {
|
||||||
|
return this.getSelected();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
|
Reference in New Issue
Block a user