diff --git a/src/components/app/app.ts b/src/components/app/app.ts
index 20436c58e7..f499b97013 100644
--- a/src/components/app/app.ts
+++ b/src/components/app/app.ts
@@ -80,7 +80,10 @@ export class App {
// During developement, navPop can be triggered by calling
// window.ClickBackButton();
if (!window['HWBackButton']) {
- window['HWBackButton'] = this.goBack.bind(this);
+ window['HWBackButton'] = () => {
+ let p = this.goBack();
+ p && p.catch(() => console.debug('hardware go back cancelled'));
+ };
}
});
}
@@ -233,7 +236,7 @@ export class App {
return this._menuCtrl.close();
}
- let navPromise = this.navPop();
+ const navPromise = this.navPop();
if (navPromise === null) {
// no views to go back to
// let's exit the app
diff --git a/src/components/nav/test/worst-case/app-module.ts b/src/components/nav/test/worst-case/app-module.ts
index e3e1e22900..983c670567 100644
--- a/src/components/nav/test/worst-case/app-module.ts
+++ b/src/components/nav/test/worst-case/app-module.ts
@@ -1,10 +1,12 @@
import { Component, NgModule } from '@angular/core';
import { IonicApp, IonicModule, NavController, NavParams } from '../../../..';
+import { DomSanitizer } from '@angular/platform-browser';
+
let LOG = '';
-function log(message: string) {
- console.log(message);
- LOG += message;
+function log(page: string, message: string, color: string) {
+ console.log(`${page}: ${message}`);
+ LOG += `${page}:${message}`;
LOG += '\n';
}
@@ -25,32 +27,32 @@ const TEMPLATE: string = `
export class Base {
constructor(public _name: string) { }
ionViewWillLoad() {
- log(`${this._name} willLoad`);
+ log(this._name, 'willLoad', 'green');
}
ionViewDidLoad() {
- log(`${this._name} didLoad`);
+ log(this._name, 'didLoad', 'green');
}
ionViewWillEnter() {
- log(`${this._name} willEnter`);
+ log(this._name, 'willEnter', 'greenyellow');
}
ionViewDidEnter() {
- log(`${this._name} didEnter`);
+ log(this._name, 'didEnter', 'cyan');
}
ionViewWillLeave() {
- log(`${this._name} willLeave`);
+ log(this._name, 'willLeave', 'greenyellow');
}
ionViewDidLeave() {
- log(`${this._name} didLeave`);
+ log(this._name, 'didLeave', 'cyan');
}
ionViewWillUnload() {
- log(`${this._name} willUnload`);
+ log(this._name, 'willUnload', 'lightgray');
}
ionViewCanLeave(): boolean|Promise {
- log(`${this._name} canLeave`);
+ log(this._name, 'canLeave', 'deeppink');
return true;
}
ionViewCanEnter(): boolean|Promise {
- log(`${this._name} canEnter`);
+ log(this._name, 'canEnter', '#ff78c1');
return true;
}
}
@@ -76,9 +78,9 @@ export class Page2 extends Base {
ionViewWillEnter() {
super.ionViewWillEnter();
if (this.counter > 0) {
- this.nav.push(Page3);
+ this.nav.push(Page3, { animated: (this.counter !== 2)});
} else if (this.counter === 0) {
- this.nav.push(Page4);
+ this.nav.push(Page4, {animate: false});
} else {
throw new Error('should not be here!');
}
@@ -90,12 +92,15 @@ export class Page2 extends Base {
template: TEMPLATE
})
export class Page3 extends Base {
- constructor(private nav: NavController) {
+ animated: boolean;
+ constructor(private nav: NavController, params: NavParams) {
super('Page3');
+ this.animated = params.get('animated');
}
+
ionViewDidEnter() {
- super.ionViewWillEnter();
- this.nav.pop();
+ super.ionViewDidEnter();
+ this.nav.pop({animate: this.animated});
}
}
@@ -262,16 +267,16 @@ export class Page8 extends Base {
- {{result}}
+
`
})
export class Results {
- result: string = 'Loading...';
- constructor(private nav: NavController) {
+ result: any;
+ constructor(private nav: NavController, private sanitizer: DomSanitizer) {
}
ionViewDidEnter() {
- this.result = LOG;
+ this.result = this.sanitizer.bypassSecurityTrustHtml(LOG);
}
}
diff --git a/src/components/tabs/tabs.ts b/src/components/tabs/tabs.ts
index ee680e941b..0a94f4ff41 100644
--- a/src/components/tabs/tabs.ts
+++ b/src/components/tabs/tabs.ts
@@ -383,7 +383,7 @@ export class Tabs extends Ion implements AfterViewInit {
let deselectedPage: ViewController;
if (deselectedTab) {
deselectedPage = deselectedTab.getActive();
- deselectedPage && deselectedPage._willLeave();
+ deselectedPage && deselectedPage._willLeave(false);
}
opts.animate = false;
diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts
index fcdb828c39..392d995013 100644
--- a/src/navigation/nav-controller-base.ts
+++ b/src/navigation/nav-controller-base.ts
@@ -270,7 +270,10 @@ export class NavControllerBase extends Ion implements NavController {
const leavingView = this.getActive();
const enteringView = this._getEnteringView(ti, leavingView);
- assert(leavingView || enteringView, 'both leavingView and enteringView are null');
+ if (!leavingView && !enteringView) {
+ ti.reject('leavingView and enteringView are null. stack is already empty');
+ return false;
+ }
// set that this nav is actively transitioning
this.setTransitioning(true);
@@ -423,7 +426,7 @@ export class NavControllerBase extends Ion implements NavController {
this._zone.run(() => {
for (i = 0; i < destroyQueue.length; i++) {
view = destroyQueue[i];
- this._willLeave(view);
+ this._willLeave(view, true);
this._didLeave(view);
this._willUnload(view);
}
@@ -682,7 +685,7 @@ export class NavControllerBase extends Ion implements NavController {
if (enteringView || leavingView) {
this._zone.run(() => {
// Here, the order is important. WillLeave must called before WillEnter.
- leavingView && this._willLeave(leavingView);
+ leavingView && this._willLeave(leavingView, !enteringView);
enteringView && this._willEnter(enteringView);
});
}
@@ -856,11 +859,11 @@ export class NavControllerBase extends Ion implements NavController {
this._app.viewDidEnter.emit(view);
}
- _willLeave(view: ViewController) {
+ _willLeave(view: ViewController, willUnload: boolean) {
assert(this.isTransitioning(), 'nav controller should be transitioning');
assert(NgZone.isInAngularZone(), 'callback should be zoned');
- view._willLeave();
+ view._willLeave(willUnload);
this.viewWillLeave.emit(view);
this._app.viewWillLeave.emit(view);
}
diff --git a/src/navigation/test/view-controller.spec.ts b/src/navigation/test/view-controller.spec.ts
index e91a7642c6..5689a4c274 100644
--- a/src/navigation/test/view-controller.spec.ts
+++ b/src/navigation/test/view-controller.spec.ts
@@ -50,7 +50,7 @@ describe('ViewController', () => {
});
// act
- viewController._willLeave();
+ viewController._willLeave(false);
}, 10000);
});
@@ -92,6 +92,7 @@ describe('ViewController', () => {
// arrange
let viewController = mockView();
let navControllerBase = mockNavController();
+ navControllerBase._isPortal = true;
mockViews(navControllerBase, [viewController]);
viewController.onWillDismiss((data: any) => {
diff --git a/src/navigation/view-controller.ts b/src/navigation/view-controller.ts
index f1ee623f25..fc07676687 100644
--- a/src/navigation/view-controller.ts
+++ b/src/navigation/view-controller.ts
@@ -38,6 +38,8 @@ export class ViewController {
private _nb: Navbar;
private _onDidDismiss: Function;
private _onWillDismiss: Function;
+ private _dismissData: any;
+ private _dismissRole: any;
private _detached: boolean;
/**
@@ -164,20 +166,16 @@ export class ViewController {
* @param {any} [role ]
* @param {NavOptions} NavOptions Options for the dismiss navigation.
* @returns {any} data Returns the data passed in, if any.
- *
*/
dismiss(data?: any, role?: any, navOptions: NavOptions = {}): Promise {
if (!this._nav) {
return Promise.resolve(false);
}
+ this._dismissData = data;
+ this._dismissRole = role;
- let options = assign({}, this._leavingOpts, navOptions);
- this._onWillDismiss && this._onWillDismiss(data, role);
- return this._nav.removeView(this, options).then(() => {
- this._onDidDismiss && this._onDidDismiss(data, role);
- this._onDidDismiss = null;
- return data;
- });
+ const options = assign({}, this._leavingOpts, navOptions);
+ return this._nav.removeView(this, options).then(() => data);
}
/**
@@ -489,9 +487,14 @@ export class ViewController {
* @private
* The view has is about to leave and no longer be the active view.
*/
- _willLeave() {
+ _willLeave(willUnload: boolean) {
this.willLeave.emit(null);
this._lifecycle('WillLeave');
+
+ if (willUnload && this._onWillDismiss) {
+ this._onWillDismiss(this._dismissData, this._dismissRole);
+ this._onWillDismiss = null;
+ }
}
/**
@@ -517,6 +520,11 @@ export class ViewController {
_willUnload() {
this.willUnload.emit(null);
this._lifecycle('WillUnload');
+
+ this._onDidDismiss && this._onDidDismiss(this._dismissData, this._dismissRole);
+ this._onDidDismiss = null;
+ this._dismissData = null;
+ this._dismissRole = null;
}
/**
@@ -537,7 +545,7 @@ export class ViewController {
this._cmp.destroy();
}
- this._nav = this._cmp = this.instance = this._cntDir = this._cntRef = this._hdrDir = this._ftrDir = this._nb = this._onWillDismiss = null;
+ this._nav = this._cmp = this.instance = this._cntDir = this._cntRef = this._hdrDir = this._ftrDir = this._nb = this._onDidDismiss = this._onWillDismiss = null;
}
/**