Skip to content

Commit

Permalink
fix(tabs): current tab still active if selected tab does not have a root
Browse files Browse the repository at this point in the history
The current selected tab should NOT be deselected (i.e. detached from change detection) if the selected tab does not have a root
ie. a tab that acts as a button to open a modal, logout etc.

Lifecycle events should not be dispatched either. Right now we are dispatching willLeave/willEnter always (this is a bug).

Closes #9392. Closes #9811. Closes #9392.
  • Loading branch information
manucorporat authored and mhartington committed Jan 6, 2017
1 parent f7b9beb commit f09c300
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 38 deletions.
85 changes: 50 additions & 35 deletions src/components/tabs/tabs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -374,54 +374,69 @@ export class Tabs extends Ion implements AfterViewInit {
return;
}

const deselectedTab = this.getSelected();
if (selectedTab === deselectedTab) {
// no change
// If the selected tab is the current selected tab, we do not switch
const currentTab = this.getSelected();
if (selectedTab === currentTab) {
return this._touchActive(selectedTab);
}

let deselectedPage: ViewController;
if (deselectedTab) {
deselectedPage = deselectedTab.getActive();
deselectedPage && deselectedPage._willLeave(false);
// If the selected tab does not have a root, we do not switch (#9392)
// it's possible the tab is only for opening modal's or signing out
// and doesn't actually have content. In the case there's no content
// for a tab then do nothing and leave the current view as is
if (!selectedTab.root) {
selectedTab.ionSelect.emit(selectedTab);
this.ionChange.emit(selectedTab);
return;
}

opts.animate = false;
// At this point we are going to perform a page switch
// Let's fire willLeave in the current tab page
let currentPage: ViewController;
if (currentTab) {
currentPage = currentTab.getActive();
currentPage && currentPage._willLeave(false);
}

// Fire willEnter in the new selected tab
const selectedPage = selectedTab.getActive();
selectedPage && selectedPage._willEnter();

selectedTab.load(opts, (alreadyLoaded: boolean) => {
selectedTab.ionSelect.emit(selectedTab);
this.ionChange.emit(selectedTab);
// Let's start the transition
opts.animate = false;
selectedTab.load(opts, () => {
if (opts.updateUrl !== false) {
this._linker.navChange(DIRECTION_SWITCH);
}
this._tabSwitchEnd(selectedTab, selectedPage, currentPage);
});
}

if (selectedTab.root) {
// only show the selectedTab if it has a root
// it's possible the tab is only for opening modal's or signing out
// and doesn't actually have content. In the case there's no content
// for a tab then do nothing and leave the current view as is
this._tabs.forEach(tab => {
tab.setSelected(tab === selectedTab);
});

if (this.tabsHighlight) {
this._highlight.select(selectedTab);
}
_tabSwitchEnd(selectedTab: Tab, selectedPage: ViewController, currentPage: ViewController) {
selectedTab.ionSelect.emit(selectedTab);
this.ionChange.emit(selectedTab);

if (opts.updateUrl !== false) {
this._linker.navChange(DIRECTION_SWITCH);
}
}
// Update tabs selection state
const tabs = this._tabs;
let tab: Tab;
for (var i = 0; i < tabs.length; i++) {
tab = tabs[i];
tab.setSelected(tab === selectedTab);
}

if (this.tabsHighlight) {
this._highlight.select(selectedTab);
}

selectedPage && selectedPage._didEnter();
deselectedPage && deselectedPage._didLeave();
// Fire didEnter/didLeave lifecycle events
selectedPage && selectedPage._didEnter();
currentPage && currentPage._didLeave();

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

/**
Expand Down
46 changes: 43 additions & 3 deletions src/components/tabs/test/advanced/app-module.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, NgModule, ViewChild } from '@angular/core';
import { /*DeepLink,*/ DeepLinkConfig, IonicApp, IonicModule, App, NavController, NavParams, ModalController, ViewController, Tabs, Tab } from '../../../..';
import { /*DeepLink,*/AlertController, DeepLinkConfig, IonicApp, IonicModule, App, NavController, NavParams, ModalController, ViewController, Tabs, Tab } from '../../../..';


// @DeepLink({ name: 'sign-in' })
Expand Down Expand Up @@ -35,7 +35,12 @@ export class TabsPage {

@ViewChild(Tabs) tabs: Tabs;

constructor(public modalCtrl: ModalController, public params: NavParams) {}
constructor(
public navCtrl: NavController,
public modalCtrl: ModalController,
public params: NavParams,
public alertCtrl: AlertController
) { }

ngAfterViewInit() {
this.tabs.ionChange.subscribe((tab: Tab) => {
Expand All @@ -51,6 +56,39 @@ export class TabsPage {
console.log('onTabChange');
}

logout() {
this.navCtrl.pop().catch(() => {
console.log('Cannot go back.');
});
}

ionViewCanLeave() {
return new Promise((resolve, reject) => {
let alert = this.alertCtrl.create({
title: 'Log out',
subTitle: 'Are you sure you want to log out?',
buttons: [
{
text: 'No',
role: 'cancel',
handler: () => {
reject();
}
},
{
text: 'Yes',
handler: () => {
alert.dismiss().then(() => {
resolve();
});
}
}
]
});
alert.present();
});
}

chat() {
console.log('Chat clicked!');
this.modalCtrl.create(ChatPage).present();
Expand Down Expand Up @@ -104,7 +142,9 @@ export class Tab1Page1 {
}

logout() {
this.app.getRootNav().setRoot(SignIn, null, { animate: true, direction: 'back' });
this.app.getRootNav().setRoot(SignIn, null, { animate: true, direction: 'back' }).catch(() => {
console.debug('logout cancelled');
});
}

ionViewWillEnter() {
Expand Down
2 changes: 2 additions & 0 deletions src/components/tabs/test/advanced/tab1page1.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
<p><button ion-button (click)="logout()">Logout</button></p>
<p><button ion-button (click)="favoritesTab()">Favorites Tab</button></p>
<p><button ion-button (click)="goBack()">Go Back</button></p>
<p><button ion-button (click)="color = !color" [color]="color ? 'primary':'secondary'">Change color</button></p>
<p>"Change color" should continue working after clicking Logout in the tabbar and cancelling (No in the alert)</p>
<p>UserId: {{userId}}</p>
<div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div>
<div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div><div f></div>
Expand Down
1 change: 1 addition & 0 deletions src/components/tabs/test/advanced/tabs.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@
<ion-tab tabTitle="Favorites" tabIcon="star" root="Tab2Page1" tabsHideOnSubPages="false"></ion-tab>
<ion-tab tabTitle="Settings" tabIcon="settings" root="Tab3Page1"></ion-tab>
<ion-tab tabTitle="Chat" tabIcon="chatbubbles" (ionSelect)="chat()" [show]="showTab"></ion-tab>
<ion-tab tabTitle="Logout" tabIcon="exit" (ionSelect)="logout()"></ion-tab>
</ion-tabs>

0 comments on commit f09c300

Please sign in to comment.