diff --git a/ionic/components/action-sheet/action-sheet.ts b/ionic/components/action-sheet/action-sheet.ts
index b93db0ed95..732f7c0fa7 100644
--- a/ionic/components/action-sheet/action-sheet.ts
+++ b/ionic/components/action-sheet/action-sheet.ts
@@ -78,20 +78,21 @@ import {ViewController} from '../nav/view-controller';
* @demo /docs/v2/demos/action-sheet/
* @see {@link /docs/v2/components#action-sheets ActionSheet Component Docs}
*/
- export class ActionSheet extends ViewController {
+export class ActionSheet extends ViewController {
- constructor(opts: ActionSheetOptions = {}) {
- opts.buttons = opts.buttons || [];
- opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
+ constructor(opts: ActionSheetOptions = {}) {
+ opts.buttons = opts.buttons || [];
+ opts.enableBackdropDismiss = isDefined(opts.enableBackdropDismiss) ? !!opts.enableBackdropDismiss : true;
- super(ActionSheetCmp, opts);
- this.viewType = 'action-sheet';
+ super(ActionSheetCmp, opts);
+ this.viewType = 'action-sheet';
+ this.isOverlay = true;
// by default, actionsheets should not fire lifecycle events of other views
// for example, when an actionsheets enters, the current active view should
// not fire its lifecycle events because it's not conceptually leaving
this.fireOtherLifecycles = false;
- }
+ }
/**
* @private
diff --git a/ionic/components/alert/alert.ts b/ionic/components/alert/alert.ts
index 57199e6878..8743b24936 100644
--- a/ionic/components/alert/alert.ts
+++ b/ionic/components/alert/alert.ts
@@ -126,6 +126,7 @@ export class Alert extends ViewController {
super(AlertCmp, opts);
this.viewType = 'alert';
+ this.isOverlay = true;
// by default, alerts should not fire lifecycle events of other views
// for example, when an alert enters, the current active view should
diff --git a/ionic/components/alert/test/basic/index.ts b/ionic/components/alert/test/basic/index.ts
index aeea05ede2..2902c5b2f5 100644
--- a/ionic/components/alert/test/basic/index.ts
+++ b/ionic/components/alert/test/basic/index.ts
@@ -1,4 +1,4 @@
-import {App, Page, Alert, NavController} from '../../../../../ionic/ionic';
+import {App, Page, Alert, Modal, NavController, ViewController} from '../../../../../ionic/ionic';
@Page({
@@ -71,9 +71,20 @@ class E2EPage {
let alert = Alert.create({
title: 'Alert',
subTitle: 'Subtitle',
- message: 'This is an alert message.',
- buttons: ['Cancel', 'Continue', 'Delete']
+ message: 'This is an alert message.'
});
+ alert.addButton('Cancel');
+ alert.addButton({
+ text: 'Open Modal',
+ handler: () => {
+ let modal = Modal.create(ModalPage);
+ this.nav.present(modal);
+
+ // do not close the alert when this button is pressed
+ return false;
+ }
+ });
+ alert.addButton('Delete');
this.nav.present(alert);
}
@@ -98,6 +109,7 @@ class E2EPage {
alert.dismiss(data);
}, 500);
+ // do not close the alert when this button is pressed
return false;
}
});
@@ -270,11 +282,33 @@ class E2EPage {
}
}
+@Page({
+ template: `
+
+
+
+
+ Modal
+
+
+ Hi, I'm Bob, and I'm a modal.
+
+ `
+})
+class ModalPage {
+ constructor(private viewCtrl: ViewController) {}
+
+ dismiss() {
+ this.viewCtrl.dismiss();
+ }
+}
+
@App({
template: ''
})
class E2EApp {
+ root;
constructor() {
this.root = E2EPage;
}
diff --git a/ionic/components/modal/modal.ts b/ionic/components/modal/modal.ts
index 2ed614c42f..b8c0009c7c 100644
--- a/ionic/components/modal/modal.ts
+++ b/ionic/components/modal/modal.ts
@@ -106,6 +106,7 @@ export class Modal extends ViewController {
constructor(componentType, data={}) {
super(componentType, data);
this.viewType = 'modal';
+ this.isOverlay = true;
}
/**
diff --git a/ionic/components/nav/nav-controller.ts b/ionic/components/nav/nav-controller.ts
index aa8eab1a7e..8d30071acb 100644
--- a/ionic/components/nav/nav-controller.ts
+++ b/ionic/components/nav/nav-controller.ts
@@ -990,10 +990,19 @@ export class NavController extends Ion {
} else {
// there are no other transitions happening but this one
// only entering/leaving should show, all others hidden
- this._views.forEach(view => {
- let shouldShow = (view === enteringView) || (view === leavingView);
+ // also if a view is an overlay or the previous view is an
+ // overlay then always show the overlay and the view before it
+ var view: ViewController;
+ var shouldShow: boolean;
+
+ for (var i = 0, ii = this._views.length; i < ii; i++) {
+ view = this._views[i];
+ shouldShow = (view === enteringView) ||
+ (view === leavingView) ||
+ view.isOverlay ||
+ (i < ii - 1 ? this._views[i + 1].isOverlay : false);
view.domCache(shouldShow, this._renderer);
- });
+ }
}
// call each view's lifecycle events
diff --git a/ionic/components/nav/test/nav-controller.spec.ts b/ionic/components/nav/test/nav-controller.spec.ts
index d4ec11ec3c..fa95264e0b 100644
--- a/ionic/components/nav/test/nav-controller.spec.ts
+++ b/ionic/components/nav/test/nav-controller.spec.ts
@@ -477,6 +477,73 @@ export function run() {
expect(navOptions.animate).toBe(false);
});
+ it('should set domCache true when isAlreadyTransitioning', () => {
+ let enteringView = new ViewController(Page1);
+ let leavingView = new ViewController(Page2);
+ let isAlreadyTransitioning = true;
+ var navOptions: NavOptions = {};
+ var done = () => {};
+ nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
+ nav._renderer = null;
+
+ spyOn(enteringView, 'domCache');
+ spyOn(leavingView, 'domCache');
+
+ nav._postRender(1, enteringView, leavingView, isAlreadyTransitioning, navOptions, done);
+
+ expect(enteringView.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ expect(leavingView.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ });
+
+ it('should set domCache true when isAlreadyTransitioning false for the entering/leaving views', () => {
+ let view1 = new ViewController(Page1);
+ let view2 = new ViewController(Page2);
+ let view3 = new ViewController(Page3);
+ let isAlreadyTransitioning = false;
+ var navOptions: NavOptions = {};
+ var done = () => {};
+ nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
+ nav._renderer = null;
+ nav._views = [view1, view2, view3];
+
+ spyOn(view1, 'domCache');
+ spyOn(view2, 'domCache');
+ spyOn(view3, 'domCache');
+
+ nav._postRender(1, view3, view2, isAlreadyTransitioning, navOptions, done);
+
+ expect(view1.domCache).toHaveBeenCalledWith(false, nav._renderer);
+ expect(view2.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ expect(view3.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ });
+
+ it('should set domCache true when isAlreadyTransitioning false for views when a view has isOverlay=true', () => {
+ let view1 = new ViewController(Page1);
+ let view2 = new ViewController(Page2);
+ let view3 = new ViewController(Page3);
+ let view4 = new ViewController(Page4);
+ let isAlreadyTransitioning = false;
+ var navOptions: NavOptions = {};
+ var done = () => {};
+ nav._beforeTrans = () => {}; //prevent running beforeTrans for tests
+ nav._renderer = null;
+ nav._views = [view1, view2, view3, view4];
+
+ view3.isOverlay = true;
+
+ spyOn(view1, 'domCache');
+ spyOn(view2, 'domCache');
+ spyOn(view3, 'domCache');
+ spyOn(view4, 'domCache');
+
+ nav._postRender(1, view4, view3, isAlreadyTransitioning, navOptions, done);
+
+ expect(view1.domCache).toHaveBeenCalledWith(false, nav._renderer);
+ expect(view2.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ expect(view3.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ expect(view4.domCache).toHaveBeenCalledWith(true, nav._renderer);
+ });
+
});
describe('_setZIndex', () => {
diff --git a/ionic/components/nav/view-controller.ts b/ionic/components/nav/view-controller.ts
index ad8792aaa3..f5637cca65 100644
--- a/ionic/components/nav/view-controller.ts
+++ b/ionic/components/nav/view-controller.ts
@@ -71,6 +71,11 @@ export class ViewController {
*/
fireOtherLifecycles: boolean = true;
+ /**
+ * @private
+ */
+ isOverlay: boolean = false;
+
/**
* @private
*/