fix(viewcontroller): onDidDismiss() is always called

fixes #8223
This commit is contained in:
Manu Mtz.-Almeida
2016-12-05 21:53:24 +01:00
committed by Adam Bradley
parent 66bbd24d8d
commit 68eb1b7cb5
6 changed files with 60 additions and 40 deletions

View File

@ -80,7 +80,10 @@ export class App {
// During developement, navPop can be triggered by calling // During developement, navPop can be triggered by calling
// window.ClickBackButton(); // window.ClickBackButton();
if (!window['HWBackButton']) { 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(); return this._menuCtrl.close();
} }
let navPromise = this.navPop(); const navPromise = this.navPop();
if (navPromise === null) { if (navPromise === null) {
// no views to go back to // no views to go back to
// let's exit the app // let's exit the app

View File

@ -1,10 +1,12 @@
import { Component, NgModule } from '@angular/core'; import { Component, NgModule } from '@angular/core';
import { IonicApp, IonicModule, NavController, NavParams } from '../../../..'; import { IonicApp, IonicModule, NavController, NavParams } from '../../../..';
import { DomSanitizer } from '@angular/platform-browser';
let LOG = ''; let LOG = '';
function log(message: string) { function log(page: string, message: string, color: string) {
console.log(message); console.log(`${page}: ${message}`);
LOG += message; LOG += `${page}:<span style="background:${color};">${message}</span>`;
LOG += '\n'; LOG += '\n';
} }
@ -25,32 +27,32 @@ const TEMPLATE: string = `
export class Base { export class Base {
constructor(public _name: string) { } constructor(public _name: string) { }
ionViewWillLoad() { ionViewWillLoad() {
log(`${this._name} willLoad`); log(this._name, 'willLoad', 'green');
} }
ionViewDidLoad() { ionViewDidLoad() {
log(`${this._name} didLoad`); log(this._name, 'didLoad', 'green');
} }
ionViewWillEnter() { ionViewWillEnter() {
log(`${this._name} willEnter`); log(this._name, 'willEnter', 'greenyellow');
} }
ionViewDidEnter() { ionViewDidEnter() {
log(`${this._name} didEnter`); log(this._name, 'didEnter', 'cyan');
} }
ionViewWillLeave() { ionViewWillLeave() {
log(`${this._name} willLeave`); log(this._name, 'willLeave', 'greenyellow');
} }
ionViewDidLeave() { ionViewDidLeave() {
log(`${this._name} didLeave`); log(this._name, 'didLeave', 'cyan');
} }
ionViewWillUnload() { ionViewWillUnload() {
log(`${this._name} willUnload`); log(this._name, 'willUnload', 'lightgray');
} }
ionViewCanLeave(): boolean|Promise<any> { ionViewCanLeave(): boolean|Promise<any> {
log(`${this._name} canLeave`); log(this._name, 'canLeave', 'deeppink');
return true; return true;
} }
ionViewCanEnter(): boolean|Promise<any> { ionViewCanEnter(): boolean|Promise<any> {
log(`${this._name} canEnter`); log(this._name, 'canEnter', '#ff78c1');
return true; return true;
} }
} }
@ -76,9 +78,9 @@ export class Page2 extends Base {
ionViewWillEnter() { ionViewWillEnter() {
super.ionViewWillEnter(); super.ionViewWillEnter();
if (this.counter > 0) { if (this.counter > 0) {
this.nav.push(Page3); this.nav.push(Page3, { animated: (this.counter !== 2)});
} else if (this.counter === 0) { } else if (this.counter === 0) {
this.nav.push(Page4); this.nav.push(Page4, {animate: false});
} else { } else {
throw new Error('should not be here!'); throw new Error('should not be here!');
} }
@ -90,12 +92,15 @@ export class Page2 extends Base {
template: TEMPLATE template: TEMPLATE
}) })
export class Page3 extends Base { export class Page3 extends Base {
constructor(private nav: NavController) { animated: boolean;
constructor(private nav: NavController, params: NavParams) {
super('Page3'); super('Page3');
this.animated = params.get('animated');
} }
ionViewDidEnter() { ionViewDidEnter() {
super.ionViewWillEnter(); super.ionViewDidEnter();
this.nav.pop(); this.nav.pop({animate: this.animated});
} }
} }
@ -262,16 +267,16 @@ export class Page8 extends Base {
</ion-navbar> </ion-navbar>
</ion-header> </ion-header>
<ion-content padding> <ion-content padding>
<pre style="font-size: 0.72em; column-count: 3;">{{result}}</pre> <pre style="font-size: 0.72em; column-count: 3;" [innerHTML]="result"></pre>
</ion-content> </ion-content>
` `
}) })
export class Results { export class Results {
result: string = 'Loading...'; result: any;
constructor(private nav: NavController) { constructor(private nav: NavController, private sanitizer: DomSanitizer) {
} }
ionViewDidEnter() { ionViewDidEnter() {
this.result = LOG; this.result = this.sanitizer.bypassSecurityTrustHtml(LOG);
} }
} }

View File

@ -383,7 +383,7 @@ export class Tabs extends Ion implements AfterViewInit {
let deselectedPage: ViewController; let deselectedPage: ViewController;
if (deselectedTab) { if (deselectedTab) {
deselectedPage = deselectedTab.getActive(); deselectedPage = deselectedTab.getActive();
deselectedPage && deselectedPage._willLeave(); deselectedPage && deselectedPage._willLeave(false);
} }
opts.animate = false; opts.animate = false;

View File

@ -270,7 +270,10 @@ export class NavControllerBase extends Ion implements NavController {
const leavingView = this.getActive(); const leavingView = this.getActive();
const enteringView = this._getEnteringView(ti, leavingView); 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 // set that this nav is actively transitioning
this.setTransitioning(true); this.setTransitioning(true);
@ -423,7 +426,7 @@ export class NavControllerBase extends Ion implements NavController {
this._zone.run(() => { this._zone.run(() => {
for (i = 0; i < destroyQueue.length; i++) { for (i = 0; i < destroyQueue.length; i++) {
view = destroyQueue[i]; view = destroyQueue[i];
this._willLeave(view); this._willLeave(view, true);
this._didLeave(view); this._didLeave(view);
this._willUnload(view); this._willUnload(view);
} }
@ -682,7 +685,7 @@ export class NavControllerBase extends Ion implements NavController {
if (enteringView || leavingView) { if (enteringView || leavingView) {
this._zone.run(() => { this._zone.run(() => {
// Here, the order is important. WillLeave must called before WillEnter. // Here, the order is important. WillLeave must called before WillEnter.
leavingView && this._willLeave(leavingView); leavingView && this._willLeave(leavingView, !enteringView);
enteringView && this._willEnter(enteringView); enteringView && this._willEnter(enteringView);
}); });
} }
@ -856,11 +859,11 @@ export class NavControllerBase extends Ion implements NavController {
this._app.viewDidEnter.emit(view); this._app.viewDidEnter.emit(view);
} }
_willLeave(view: ViewController) { _willLeave(view: ViewController, willUnload: boolean) {
assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(this.isTransitioning(), 'nav controller should be transitioning');
assert(NgZone.isInAngularZone(), 'callback should be zoned'); assert(NgZone.isInAngularZone(), 'callback should be zoned');
view._willLeave(); view._willLeave(willUnload);
this.viewWillLeave.emit(view); this.viewWillLeave.emit(view);
this._app.viewWillLeave.emit(view); this._app.viewWillLeave.emit(view);
} }

View File

@ -50,7 +50,7 @@ describe('ViewController', () => {
}); });
// act // act
viewController._willLeave(); viewController._willLeave(false);
}, 10000); }, 10000);
}); });
@ -92,6 +92,7 @@ describe('ViewController', () => {
// arrange // arrange
let viewController = mockView(); let viewController = mockView();
let navControllerBase = mockNavController(); let navControllerBase = mockNavController();
navControllerBase._isPortal = true;
mockViews(navControllerBase, [viewController]); mockViews(navControllerBase, [viewController]);
viewController.onWillDismiss((data: any) => { viewController.onWillDismiss((data: any) => {

View File

@ -38,6 +38,8 @@ export class ViewController {
private _nb: Navbar; private _nb: Navbar;
private _onDidDismiss: Function; private _onDidDismiss: Function;
private _onWillDismiss: Function; private _onWillDismiss: Function;
private _dismissData: any;
private _dismissRole: any;
private _detached: boolean; private _detached: boolean;
/** /**
@ -164,20 +166,16 @@ export class ViewController {
* @param {any} [role ] * @param {any} [role ]
* @param {NavOptions} NavOptions Options for the dismiss navigation. * @param {NavOptions} NavOptions Options for the dismiss navigation.
* @returns {any} data Returns the data passed in, if any. * @returns {any} data Returns the data passed in, if any.
*
*/ */
dismiss(data?: any, role?: any, navOptions: NavOptions = {}): Promise<any> { dismiss(data?: any, role?: any, navOptions: NavOptions = {}): Promise<any> {
if (!this._nav) { if (!this._nav) {
return Promise.resolve(false); return Promise.resolve(false);
} }
this._dismissData = data;
this._dismissRole = role;
let options = assign({}, this._leavingOpts, navOptions); const options = assign({}, this._leavingOpts, navOptions);
this._onWillDismiss && this._onWillDismiss(data, role); return this._nav.removeView(this, options).then(() => data);
return this._nav.removeView(this, options).then(() => {
this._onDidDismiss && this._onDidDismiss(data, role);
this._onDidDismiss = null;
return data;
});
} }
/** /**
@ -489,9 +487,14 @@ export class ViewController {
* @private * @private
* The view has is about to leave and no longer be the active view. * The view has is about to leave and no longer be the active view.
*/ */
_willLeave() { _willLeave(willUnload: boolean) {
this.willLeave.emit(null); this.willLeave.emit(null);
this._lifecycle('WillLeave'); this._lifecycle('WillLeave');
if (willUnload && this._onWillDismiss) {
this._onWillDismiss(this._dismissData, this._dismissRole);
this._onWillDismiss = null;
}
} }
/** /**
@ -517,6 +520,11 @@ export class ViewController {
_willUnload() { _willUnload() {
this.willUnload.emit(null); this.willUnload.emit(null);
this._lifecycle('WillUnload'); 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._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;
} }
/** /**