fix(overlay): do not dom cache views before overlays

Closes #5483
This commit is contained in:
Adam Bradley
2016-02-21 00:03:58 -06:00
parent 4fabadecb7
commit 4cae151d47
7 changed files with 131 additions and 13 deletions

View File

@ -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

View File

@ -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

View File

@ -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: `
<ion-toolbar>
<ion-buttons>
<button (click)="dismiss()">Close</button>
</ion-buttons>
<ion-title>Modal</ion-title>
</ion-toolbar>
<ion-content padding>
Hi, I'm Bob, and I'm a modal.
</ion-content>
`
})
class ModalPage {
constructor(private viewCtrl: ViewController) {}
dismiss() {
this.viewCtrl.dismiss();
}
}
@App({
template: '<ion-nav [root]="root"></ion-nav>'
})
class E2EApp {
root;
constructor() {
this.root = E2EPage;
}

View File

@ -106,6 +106,7 @@ export class Modal extends ViewController {
constructor(componentType, data={}) {
super(componentType, data);
this.viewType = 'modal';
this.isOverlay = true;
}
/**

View File

@ -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

View File

@ -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', () => {

View File

@ -71,6 +71,11 @@ export class ViewController {
*/
fireOtherLifecycles: boolean = true;
/**
* @private
*/
isOverlay: boolean = false;
/**
* @private
*/