Skip to content

Commit d98f3c9

Browse files
committed
feat(tabs): track tab selecting history, create previousTab() method
1 parent 6f8f2ab commit d98f3c9

File tree

2 files changed

+251
-17
lines changed

2 files changed

+251
-17
lines changed

src/components/tabs/tabs.ts

Lines changed: 39 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ import {ViewController} from '../nav/view-controller';
138138
'</ion-navbar-section>' +
139139
'<ion-tabbar-section>' +
140140
'<tabbar role="tablist">' +
141-
'<a *ngFor="let t of _tabs" [tab]="t" class="tab-button" [class.tab-disabled]="!t.enabled" [class.tab-hidden]="!t.show" role="tab" href="#">' +
141+
'<a *ngFor="let t of _tabs" [tab]="t" class="tab-button" [class.tab-disabled]="!t.enabled" [class.tab-hidden]="!t.show" role="tab" href="#" (ionSelect)="select($event)">' +
142142
'<ion-icon *ngIf="t.tabIcon" [name]="t.tabIcon" [isActive]="t.isSelected" class="tab-button-icon"></ion-icon>' +
143143
'<span *ngIf="t.tabTitle" class="tab-button-text">{{t.tabTitle}}</span>' +
144144
'<ion-badge *ngIf="t.tabBadge" class="tab-badge" [ngClass]="\'badge-\' + t.tabBadgeStyle">{{t.tabBadge}}</ion-badge>' +
@@ -175,6 +175,11 @@ export class Tabs extends Ion {
175175
*/
176176
navbarContainerRef: ViewContainerRef;
177177

178+
/**
179+
* @private
180+
*/
181+
selectHistory: string[] = [];
182+
178183
/**
179184
* @private
180185
*/
@@ -213,12 +218,7 @@ export class Tabs extends Ion {
213218
/**
214219
* @private
215220
*/
216-
@ViewChildren(TabButton) private _btns: any;
217-
218-
/**
219-
* @private
220-
*/
221-
parent: any;
221+
parent: NavController;
222222

223223
constructor(
224224
@Optional() parent: NavController,
@@ -271,12 +271,6 @@ export class Tabs extends Ion {
271271
});
272272
}
273273

274-
this._btns.toArray().forEach((tabButton: TabButton) => {
275-
tabButton.ionSelect.subscribe((tab: Tab) => {
276-
this.select(tab);
277-
});
278-
});
279-
280274
let preloadTabs = (isBlank(this.preloadTabs) ? this._config.getBoolean('preloadTabs') : isTrueProperty(this.preloadTabs));
281275

282276
// get the selected index
@@ -333,11 +327,11 @@ export class Tabs extends Ion {
333327
}
334328

335329
/**
336-
* @param {number} index Index of the tab you want to select
330+
* @param {number|Tab} tabOrIndex Index, or the Tab instance, of the tab to select.
337331
*/
338-
select(tabOrIndex: any) {
339-
let selectedTab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
340-
if (!selectedTab) {
332+
select(tabOrIndex: number | Tab) {
333+
let selectedTab: Tab = (typeof tabOrIndex === 'number' ? this.getByIndex(tabOrIndex) : tabOrIndex);
334+
if (isBlank(selectedTab)) {
341335
return;
342336
}
343337

@@ -390,9 +384,37 @@ export class Tabs extends Ion {
390384
this._onReady = null;
391385
}
392386

387+
// track the order of which tabs have been selected, by their index
388+
// do not track if the tab index is the same as the previous
389+
if (this.selectHistory[this.selectHistory.length - 1] !== selectedTab.id) {
390+
this.selectHistory.push(selectedTab.id);
391+
}
392+
393393
});
394394
}
395395

396+
/**
397+
* Get the previously selected Tab which is currently not disabled or hidden.
398+
* @param {boolean} trimHistory If the selection history should be trimmed up to the previous tab selection or not.
399+
* @returns {Tab}
400+
*/
401+
previousTab(trimHistory: boolean = true): Tab {
402+
// walk backwards through the tab selection history
403+
// and find the first previous tab that is enabled and shown
404+
console.log('run previousTab', this.selectHistory)
405+
for (var i = this.selectHistory.length - 2; i >= 0; i--) {
406+
var tab = this._tabs.find(t => t.id === this.selectHistory[i]);
407+
if (tab && tab.enabled && tab.show) {
408+
if (trimHistory) {
409+
this.selectHistory.splice(i + 1);
410+
}
411+
return tab;
412+
}
413+
}
414+
415+
return null;
416+
}
417+
396418
/**
397419
* @param {number} index Index of the tab you want to get
398420
* @returns {Tab} Returns the tab who's index matches the one passed

src/components/tabs/test/tabs.spec.ts

Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
import {Component} from '@angular/core';
2+
import {App, Nav, Tabs, Tab, NavOptions, Config, ViewController, Platform} from '../../../../src';
3+
4+
export function run() {
5+
6+
describe('Tabs', () => {
7+
8+
describe('previousTab', () => {
9+
10+
it('should find the previous tab when there has been 3 selections', () => {
11+
var tabs = mockTabs();
12+
var tab0 = mockTab(tabs);
13+
var tab1 = mockTab(tabs);
14+
var tab2 = mockTab(tabs);
15+
tabs.add(tab0);
16+
tabs.add(tab1);
17+
tabs.add(tab2);
18+
tab0.root = SomePage;
19+
tab1.root = SomePage;
20+
tab2.root = SomePage;
21+
22+
tabs.select(tab0);
23+
tabs.select(tab1);
24+
tabs.select(tab2);
25+
26+
expect(tabs.selectHistory).toEqual([tab0.id, tab1.id, tab2.id]);
27+
28+
expect(tabs.previousTab(true)).toEqual(tab1);
29+
expect(tabs.selectHistory).toEqual([tab0.id, tab1.id]);
30+
31+
expect(tabs.previousTab(true)).toEqual(tab0);
32+
expect(tabs.selectHistory).toEqual([tab0.id]);
33+
});
34+
35+
it('should not find a previous tab when there has only been one selection', () => {
36+
var tabs = mockTabs();
37+
var tab0 = mockTab(tabs);
38+
var tab1 = mockTab(tabs);
39+
tabs.add(tab0);
40+
tabs.add(tab1);
41+
tab0.root = SomePage;
42+
tab1.root = SomePage;
43+
44+
tabs.select(tab0);
45+
46+
expect(tabs.previousTab(true)).toEqual(null);
47+
});
48+
49+
it('should not find a previous tab when theres no history', () => {
50+
var tabs = mockTabs();
51+
expect(tabs.selectHistory.length).toEqual(0);
52+
expect(tabs.previousTab(true)).toEqual(null);
53+
});
54+
55+
it('should track tab selections', () => {
56+
var tabs = mockTabs();
57+
var tab0 = mockTab(tabs);
58+
var tab1 = mockTab(tabs);
59+
tabs.add(tab0);
60+
tabs.add(tab1);
61+
tab0.root = SomePage;
62+
tab1.root = SomePage;
63+
64+
expect(tabs.selectHistory.length).toEqual(0);
65+
66+
tabs.select(tab0);
67+
expect(tabs.selectHistory[0]).toEqual(tab0.id);
68+
expect(tabs.selectHistory.length).toEqual(1);
69+
70+
tabs.select(tab1);
71+
expect(tabs.selectHistory[0]).toEqual(tab0.id);
72+
expect(tabs.selectHistory[1]).toEqual(tab1.id);
73+
expect(tabs.selectHistory.length).toEqual(2);
74+
75+
tabs.select(tab0);
76+
expect(tabs.selectHistory[0]).toEqual(tab0.id);
77+
expect(tabs.selectHistory[1]).toEqual(tab1.id);
78+
expect(tabs.selectHistory[2]).toEqual(tab0.id);
79+
expect(tabs.selectHistory.length).toEqual(3);
80+
});
81+
82+
});
83+
84+
describe('select', () => {
85+
86+
it('should select tab by tab instance', () => {
87+
var tabs = mockTabs();
88+
var tab0 = mockTab(tabs);
89+
var tab1 = mockTab(tabs);
90+
tabs.add(tab0);
91+
tabs.add(tab1);
92+
93+
tab0.root = SomePage;
94+
tab1.root = SomePage;
95+
96+
tabs.select(tab1);
97+
98+
expect(tab0.isSelected).toEqual(false);
99+
expect(tab1.isSelected).toEqual(true);
100+
});
101+
102+
it('should select tab by index', () => {
103+
var tabs = mockTabs();
104+
var tab0 = mockTab(tabs);
105+
var tab1 = mockTab(tabs);
106+
tabs.add(tab0);
107+
tabs.add(tab1);
108+
109+
tab0.root = SomePage;
110+
tab1.root = SomePage;
111+
112+
expect(tab0.isSelected).toBeUndefined();
113+
expect(tab1.isSelected).toBeUndefined();
114+
115+
tabs.select(0);
116+
117+
expect(tab0.isSelected).toEqual(true);
118+
expect(tab1.isSelected).toEqual(false);
119+
});
120+
121+
it('should not select an invalid tab index', () => {
122+
var tabs = mockTabs();
123+
var tab0 = mockTab(tabs);
124+
var tab1 = mockTab(tabs);
125+
tabs.add(tab0);
126+
tabs.add(tab1);
127+
128+
expect(tabs.select(22)).toBeUndefined();
129+
});
130+
131+
});
132+
133+
describe('getByIndex', () => {
134+
135+
it('should get the tab', () => {
136+
var tabs = mockTabs();
137+
var tab0 = mockTab(tabs);
138+
tab0.setRoot()
139+
var tab1 = mockTab(tabs);
140+
tabs.add(tab0);
141+
tabs.add(tab1);
142+
143+
expect(tabs.getIndex(tab0)).toEqual(0);
144+
expect(tabs.getIndex(tab1)).toEqual(1);
145+
});
146+
147+
});
148+
149+
describe('getSelected', () => {
150+
151+
it('should get the selected tab', () => {
152+
var tabs = mockTabs();
153+
var tab0 = mockTab(tabs);
154+
var tab1 = mockTab(tabs);
155+
tabs.add(tab0);
156+
tabs.add(tab1);
157+
158+
tab1.setSelected(true);
159+
160+
expect(tabs.getSelected()).toEqual(tab1);
161+
});
162+
163+
it('should get null if no selected tab', () => {
164+
var tabs = mockTabs();
165+
var tab0 = mockTab(tabs);
166+
var tab1 = mockTab(tabs);
167+
tabs.add(tab0);
168+
tabs.add(tab1);
169+
170+
expect(tabs.getSelected()).toEqual(null);
171+
});
172+
173+
});
174+
175+
var app: App;
176+
var config: Config;
177+
var platform: Platform;
178+
var _cd: any;
179+
180+
function mockNav(): Nav {
181+
return new Nav(null, null, null, config, null, null, null, null, null);
182+
}
183+
184+
function mockTabs(): Tabs {
185+
return new Tabs(null, null, null, config, null, null, null);
186+
}
187+
188+
function mockTab(parentTabs: Tabs): Tab {
189+
var tab = new Tab(parentTabs, app, config, null, null, null, null, null, _cd);
190+
tab.load = function(opts: any, cb: Function) {
191+
cb();
192+
};
193+
return tab;
194+
}
195+
196+
@Component({})
197+
class SomePage {}
198+
199+
beforeEach(() => {
200+
config = new Config();
201+
platform = new Platform();
202+
app = new App(config, null, platform);
203+
_cd = {
204+
reattach: function(){},
205+
detach: function(){}
206+
};
207+
});
208+
209+
});
210+
211+
212+
}

0 commit comments

Comments
 (0)