feat(app): getActiveNav() method

This commit is contained in:
Adam Bradley
2016-04-07 20:45:51 -05:00
parent fe31ebf73b
commit 77772370bf
6 changed files with 201 additions and 11 deletions

View File

@ -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.

View 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);
});
});
}

View File

@ -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);
}
} }
/** /**

View File

@ -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);
}
} }
/** /**

View File

@ -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

View File

@ -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
*/ */