diff --git a/src/components/tabs/tabs.ts b/src/components/tabs/tabs.ts index d162f1405c1..b40985cc48a 100644 --- a/src/components/tabs/tabs.ts +++ b/src/components/tabs/tabs.ts @@ -138,7 +138,7 @@ import {ViewController} from '../nav/view-controller'; '' + '' + '' + - '' + + '' + '' + '{{t.tabTitle}}' + '{{t.tabBadge}}' + @@ -175,6 +175,11 @@ export class Tabs extends Ion { */ navbarContainerRef: ViewContainerRef; + /** + * @private + */ + selectHistory: string[] = []; + /** * @private */ @@ -213,12 +218,7 @@ export class Tabs extends Ion { /** * @private */ - @ViewChildren(TabButton) private _btns: any; - - /** - * @private - */ - parent: any; + parent: NavController; constructor( @Optional() parent: NavController, @@ -271,12 +271,6 @@ export class Tabs extends Ion { }); } - this._btns.toArray().forEach((tabButton: TabButton) => { - tabButton.ionSelect.subscribe((tab: Tab) => { - this.select(tab); - }); - }); - let preloadTabs = (isBlank(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs)); // get the selected index @@ -333,11 +327,11 @@ export class Tabs extends Ion { } /** - * @param {number} index Index of the tab you want to select + * @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select. */ - select(tabOrIndex: any) { - let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex); - if (!selectedTab) { + select(tabOrIndex: number | Tab) { + let selectedTab: Tab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex); + if (isBlank(selectedTab)) { return; } @@ -390,9 +384,37 @@ export class Tabs extends Ion { this._onReady = null; } + // track the order of which tabs have been selected, by their index + // do not track if the tab index is the same as the previous + if (this.selectHistory[this.selectHistory.length - 1] !== selectedTab.id) { + this.selectHistory.push(selectedTab.id); + } + }); } + /** + * Get the previously selected Tab which is currently not disabled or hidden. + * @param {boolean} trimHistory If the selection history should be trimmed up to the previous tab selection or not. + * @returns {Tab} + */ + previousTab(trimHistory: boolean = true): Tab { + // walk backwards through the tab selection history + // and find the first previous tab that is enabled and shown + console.log('run previousTab', this.selectHistory) + for (var i = this.selectHistory.length - 2; i >= 0; i--) { + var tab = this._tabs.find(t => t.id === this.selectHistory[i]); + if (tab && tab.enabled && tab.show) { + if (trimHistory) { + this.selectHistory.splice(i + 1); + } + return tab; + } + } + + return null; + } + /** * @param {number} index Index of the tab you want to get * @returns {Tab} Returns the tab who's index matches the one passed diff --git a/src/components/tabs/test/tabs.spec.ts b/src/components/tabs/test/tabs.spec.ts new file mode 100644 index 00000000000..befc4c58857 --- /dev/null +++ b/src/components/tabs/test/tabs.spec.ts @@ -0,0 +1,212 @@ +import {Component} from '@angular/core'; +import {App, Nav, Tabs, Tab, NavOptions, Config, ViewController, Platform} from '../../../../src'; + +export function run() { + +describe('Tabs', () => { + + describe('previousTab', () => { + + it('should find the previous tab when there has been 3 selections', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + var tab2 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + tabs.add(tab2); + tab0.root = SomePage; + tab1.root = SomePage; + tab2.root = SomePage; + + tabs.select(tab0); + tabs.select(tab1); + tabs.select(tab2); + + expect(tabs.selectHistory).toEqual([tab0.id, tab1.id, tab2.id]); + + expect(tabs.previousTab(true)).toEqual(tab1); + expect(tabs.selectHistory).toEqual([tab0.id, tab1.id]); + + expect(tabs.previousTab(true)).toEqual(tab0); + expect(tabs.selectHistory).toEqual([tab0.id]); + }); + + it('should not find a previous tab when there has only been one selection', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + tab0.root = SomePage; + tab1.root = SomePage; + + tabs.select(tab0); + + expect(tabs.previousTab(true)).toEqual(null); + }); + + it('should not find a previous tab when theres no history', () => { + var tabs = mockTabs(); + expect(tabs.selectHistory.length).toEqual(0); + expect(tabs.previousTab(true)).toEqual(null); + }); + + it('should track tab selections', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + tab0.root = SomePage; + tab1.root = SomePage; + + expect(tabs.selectHistory.length).toEqual(0); + + tabs.select(tab0); + expect(tabs.selectHistory[0]).toEqual(tab0.id); + expect(tabs.selectHistory.length).toEqual(1); + + tabs.select(tab1); + expect(tabs.selectHistory[0]).toEqual(tab0.id); + expect(tabs.selectHistory[1]).toEqual(tab1.id); + expect(tabs.selectHistory.length).toEqual(2); + + tabs.select(tab0); + expect(tabs.selectHistory[0]).toEqual(tab0.id); + expect(tabs.selectHistory[1]).toEqual(tab1.id); + expect(tabs.selectHistory[2]).toEqual(tab0.id); + expect(tabs.selectHistory.length).toEqual(3); + }); + + }); + + describe('select', () => { + + it('should select tab by tab instance', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + tab0.root = SomePage; + tab1.root = SomePage; + + tabs.select(tab1); + + expect(tab0.isSelected).toEqual(false); + expect(tab1.isSelected).toEqual(true); + }); + + it('should select tab by index', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + tab0.root = SomePage; + tab1.root = SomePage; + + expect(tab0.isSelected).toBeUndefined(); + expect(tab1.isSelected).toBeUndefined(); + + tabs.select(0); + + expect(tab0.isSelected).toEqual(true); + expect(tab1.isSelected).toEqual(false); + }); + + it('should not select an invalid tab index', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + expect(tabs.select(22)).toBeUndefined(); + }); + + }); + + describe('getByIndex', () => { + + it('should get the tab', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + tab0.setRoot() + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + expect(tabs.getIndex(tab0)).toEqual(0); + expect(tabs.getIndex(tab1)).toEqual(1); + }); + + }); + + describe('getSelected', () => { + + it('should get the selected tab', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + tab1.setSelected(true); + + expect(tabs.getSelected()).toEqual(tab1); + }); + + it('should get null if no selected tab', () => { + var tabs = mockTabs(); + var tab0 = mockTab(tabs); + var tab1 = mockTab(tabs); + tabs.add(tab0); + tabs.add(tab1); + + expect(tabs.getSelected()).toEqual(null); + }); + + }); + + var app: App; + var config: Config; + var platform: Platform; + var _cd: any; + + function mockNav(): Nav { + return new Nav(null, null, null, config, null, null, null, null, null); + } + + function mockTabs(): Tabs { + return new Tabs(null, null, null, config, null, null, null); + } + + function mockTab(parentTabs: Tabs): Tab { + var tab = new Tab(parentTabs, app, config, null, null, null, null, null, _cd); + tab.load = function(opts: any, cb: Function) { + cb(); + }; + return tab; + } + + @Component({}) + class SomePage {} + + beforeEach(() => { + config = new Config(); + platform = new Platform(); + app = new App(config, null, platform); + _cd = { + reattach: function(){}, + detach: function(){} + }; + }); + +}); + + +}