fix(nav): adds public willLoad lifecycle event

* fix(nav): adds public willLoad lifecycle event

* test(menu): adds more asserts
This commit is contained in:
Manu Mtz.-Almeida
2016-11-01 19:12:29 +01:00
committed by Adam Bradley
parent 504e6e0440
commit 033e1eae17
9 changed files with 195 additions and 26 deletions

View File

@ -2,7 +2,7 @@ import { ChangeDetectionStrategy, Component, ContentChild, ElementRef, EventEmit
import { Backdrop } from '../backdrop/backdrop';
import { Config } from '../../config/config';
import { isTrueProperty } from '../../util/util';
import { isTrueProperty, assert } from '../../util/util';
import { Keyboard } from '../../util/keyboard';
import { MenuContentGesture } from './menu-gestures';
import { MenuController } from './menu-controller';
@ -192,7 +192,6 @@ export class Menu {
private _cntEle: HTMLElement;
private _cntGesture: MenuContentGesture;
private _type: MenuType;
private _resizeUnreg: Function;
private _isEnabled: boolean = true;
private _isSwipeEnabled: boolean = true;
private _isAnimating: boolean = false;
@ -472,6 +471,8 @@ export class Menu {
}
private _before() {
assert(this._isAnimating === false, '_before should be called when we are not animating');
// this places the menu into the correct location before it animates in
// this css class doesn't actually kick off any animations
this.menuContent && this.menuContent.resize();
@ -482,6 +483,8 @@ export class Menu {
}
private _after(isOpen: boolean) {
assert(this._isAnimating === true, '_after should be called when we are animating');
// keep opening/closing the menu disabled for a touch more yet
// only add listeners/css if it's enabled and isOpen
// and only remove listeners/css if it's not open
@ -516,21 +519,21 @@ export class Menu {
/**
* @private
*/
open() {
open(): Promise<boolean> {
return this.setOpen(true);
}
/**
* @private
*/
close() {
close(): Promise<boolean> {
return this.setOpen(false);
}
/**
* @private
*/
toggle() {
toggle(): Promise<boolean> {
return this.setOpen(!this.isOpen);
}
@ -633,12 +636,10 @@ export class Menu {
this._events.unlistenAll();
this._cntGesture && this._cntGesture.destroy();
this._type && this._type.destroy();
this._resizeUnreg && this._resizeUnreg();
this._cntGesture = null;
this._type = null;
this._cntEle = null;
this._resizeUnreg = null;
}
}

View File

@ -30,7 +30,7 @@ export class ModalCmp {
this._bdDismiss = _navParams.data.opts.enableBackdropDismiss;
}
ionViewWillLoad() {
ionViewPreLoad() {
this._load(this._navParams.data.component);
}

View File

@ -149,6 +149,7 @@ export class E2EPage {
<button ion-button full (click)="submit()">Submit</button>
<p>ionViewCanEnter ({{called.ionViewCanEnter}})</p>
<p>ionViewCanLeave ({{called.ionViewCanLeave}})</p>
<p>ionViewWillLoad ({{called.ionViewWillLoad}})</p>
<p>ionViewDidLoad ({{called.ionViewDidLoad}})</p>
<p>ionViewWillEnter ({{called.ionViewWillEnter}})</p>
<p>ionViewDidEnter ({{called.ionViewDidEnter}})</p>
@ -178,6 +179,7 @@ export class ModalPassData {
this.called = {
ionViewCanEnter: 0,
ionViewCanLeave: 0,
ionViewWillLoad: 0,
ionViewDidLoad: 0,
ionViewWillEnter: 0,
ionViewDidEnter: 0,
@ -213,6 +215,11 @@ export class ModalPassData {
});
}
ionViewWillLoad() {
console.log('ModalPassData ionViewWillLoad fired');
this.called.ionViewWillLoad++;
}
ionViewDidLoad() {
console.log('ModalPassData ionViewDidLoad fired');
this.called.ionViewDidLoad++;
@ -400,6 +407,7 @@ export class ContactUs {
<ion-content padding>
<p>ionViewCanEnter ({{called.ionViewCanEnter}})</p>
<p>ionViewCanLeave ({{called.ionViewCanLeave}})</p>
<p>ionViewWillLoad ({{called.ionViewWillLoad}})</p>
<p>ionViewDidLoad ({{called.ionViewDidLoad}})</p>
<p>ionViewWillEnter ({{called.ionViewWillEnter}})</p>
<p>ionViewDidEnter ({{called.ionViewDidEnter}})</p>
@ -441,6 +449,7 @@ export class ModalFirstPage {
this.called = {
ionViewCanEnter: 0,
ionViewCanLeave: 0,
ionViewWillLoad: 0,
ionViewDidLoad: 0,
ionViewWillEnter: 0,
ionViewDidEnter: 0,
@ -479,6 +488,11 @@ export class ModalFirstPage {
return true;
}
ionViewWillLoad() {
console.log('ModalFirstPage ionViewWillLoad fired');
this.called.ionViewWillLoad++;
}
ionViewDidLoad() {
console.log('ModalFirstPage ionViewDidLoad fired');
this.called.ionViewDidLoad++;

View File

@ -1,15 +1,22 @@
import { NgModule, Component, ViewChild } from '@angular/core';
import { App, AlertController, Content, DeepLinkConfig, IonicApp, IonicModule, Label, NavController, NavParams, Tabs, Tab, ModalController, ViewController } from '../../../..';
import { App, AlertController, Content, DeepLinkConfig, IonicApp, IonicModule, NavController, NavParams, Tabs, Tab, ModalController, ViewController } from '../../../..';
@Component({
selector: 'my-cmp2',
template: `<span style="color:green">{{value}}</span>`
})
export class MyCmpTest2 {
value: string = 'Test Failed';
}
@Component({
selector: 'my-cmp',
template: `<ion-label>My Custom Component Test <ion-icon name="star"></ion-icon>
<span style="color:green">{{value}}</span></ion-label>`
template: `<my-cmp2></my-cmp2> <span style="color:green">{{value}}</span>`
})
export class MyCmpTest {
@ViewChild(Label) _label: Label;
label: Label;
value: string = '';
@ViewChild(MyCmpTest2) _label: MyCmpTest2;
label: MyCmpTest2;
value: string = 'Test Failed';
ngOnInit() {
this.label = this._label;
@ -34,6 +41,7 @@ export class MyCmpTest {
<div padding>
<p>ionViewCanEnter ({{called.ionViewCanEnter}})</p>
<p>ionViewCanLeave ({{called.ionViewCanLeave}})</p>
<p>ionViewWillLoad ({{called.ionViewWillLoad}})</p>
<p>ionViewDidLoad ({{called.ionViewDidLoad}})</p>
<p>ionViewWillEnter ({{called.ionViewWillEnter}})</p>
<p>ionViewDidEnter ({{called.ionViewDidEnter}})</p>
@ -91,6 +99,7 @@ export class FirstPage {
this.called = {
ionViewCanEnter: 0,
ionViewCanLeave: 0,
ionViewWillLoad: 0,
ionViewDidLoad: 0,
ionViewWillEnter: 0,
ionViewDidEnter: 0,
@ -104,11 +113,11 @@ export class FirstPage {
for (var i = 1; i <= 50; i++) {
this.pages.push(i);
}
// if (!this.myCmp || !this.content || !this.myCmp.label) {
// throw new Error('children are not loaded');
// }
this.myCmp.value = 'root!';
// this.myCmp.label.color = 'primary';
if (!this.myCmp || !this.content || !this.myCmp.label) {
throw new Error('children are not loaded');
}
this.myCmp.value = '👍 self test passed!';
this.myCmp.label.value = '👍 children test passed!';
this.called.ionViewDidLoad++;
}
@ -810,6 +819,7 @@ export const deepLinkConfig: DeepLinkConfig = {
RedirectPage,
AnotherPage,
MyCmpTest,
MyCmpTest2,
FullPage,
PrimaryHeaderPage,
TabsPage,

View File

@ -423,7 +423,7 @@ export class PickerCmp {
this.lastClick = 0;
}
ionViewDidLoad() {
ionViewWillLoad() {
// normalize the data
let data = this.d;

View File

@ -60,7 +60,7 @@ export class PopoverCmp {
this.id = (++popoverIds);
}
ionViewWillLoad() {
ionViewPreLoad() {
let activeElement: any = document.activeElement;
if (document.activeElement) {
activeElement.blur();

View File

@ -0,0 +1,129 @@
import { Component, NgModule } from '@angular/core';
import { IonicApp, IonicModule, NavController, AlertController } from '../../../..';
//
// Tab 1
//
@Component({
template: `
<ion-header>
<ion-navbar>
<ion-title>Lifecyles</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<p>ionViewCanEnter ({{called.ionViewCanEnter}})</p>
<p>ionViewCanLeave ({{called.ionViewCanLeave}})</p>
<p>ionViewWillLoad ({{called.ionViewWillLoad}})</p>
<p>ionViewDidLoad ({{called.ionViewDidLoad}})</p>
<p>ionViewWillEnter ({{called.ionViewWillEnter}})</p>
<p>ionViewDidEnter ({{called.ionViewDidEnter}})</p>
<p>ionViewWillLeave ({{called.ionViewWillLeave}})</p>
<p>ionViewDidLeave ({{called.ionViewDidLeave}})</p>
<button ion-button (click)="push()">push()</button>
<button ion-button (click)="openAlert()">open alert</button>
</ion-content>
`
})
export class Tab1 {
called: any;
constructor(private alertCtrl: AlertController, private navCtrl: NavController) {
this.called = {
ionViewCanEnter: 0,
ionViewCanLeave: 0,
ionViewWillLoad: 0,
ionViewDidLoad: 0,
ionViewWillEnter: 0,
ionViewDidEnter: 0,
ionViewWillLeave: 0,
ionViewDidLeave: 0
};
}
push() {
this.navCtrl.push(Tab1);
}
openAlert() {
this.alertCtrl.create({
title: 'Example'
}).present();
}
ionViewCanEnter() {
this.called.ionViewCanEnter++;
return true;
}
ionViewCanLeave() {
this.called.ionViewCanLeave++;
return true;
}
ionViewWillLoad() {
this.called.ionViewWillLoad++;
}
ionViewDidLoad() {
this.called.ionViewDidLoad++;
}
ionViewWillEnter() {
this.called.ionViewWillEnter++;
}
ionViewDidEnter() {
this.called.ionViewDidEnter++;
}
ionViewWillLeave() {
this.called.ionViewWillLeave++;
}
ionViewDidLeave() {
this.called.ionViewDidLeave++;
}
}
@Component({
template: `
<ion-tabs>
<ion-tab tabTitle="Plain List" tabIcon="star" [root]="root"></ion-tab>
<ion-tab tabTitle="Schedule" tabIcon="globe" [root]="root"></ion-tab>
<ion-tab tabTitle="Stopwatch" tabIcon="logo-facebook" [root]="root"></ion-tab>
</ion-tabs>
`
})
export class TabsPage {
root = Tab1;
}
@Component({
template: `<ion-nav [root]="root"></ion-nav>`
})
export class E2EApp {
root = TabsPage;
}
@NgModule({
declarations: [
E2EApp,
Tab1,
TabsPage
],
imports: [
IonicModule.forRoot(E2EApp, {
tabsHighlight: true,
})
],
bootstrap: [IonicApp],
entryComponents: [
E2EApp,
Tab1,
TabsPage
]
})
export class AppModule {}

View File

@ -419,12 +419,15 @@ export class NavControllerBase extends Ion implements NavController {
// create ComponentRef and set it to the entering view
enteringView.init(componentFactory.create(childInjector, []));
enteringView._state = ViewState.INITIALIZED;
this._willLoad(enteringView);
this._preLoad(enteringView);
}
_viewAttachToDOM(view: ViewController, componentRef: ComponentRef<any>, viewport: ViewContainerRef) {
assert(view._state === ViewState.INITIALIZED, 'view state must be INITIALIZED');
// fire willLoad before change detection runs
this._willLoad(view);
// render the component ref instance to the DOM
// ******** DOM WRITE ****************
viewport.insert(componentRef.hostView, viewport.length);
@ -438,14 +441,11 @@ export class NavControllerBase extends Ion implements NavController {
this._renderer.setElementClass(pageElement, view._cssClass, true);
}
// TODO:
// componentRef.changeDetectorRef.detectChanges();
componentRef.changeDetectorRef.detectChanges();
// successfully finished loading the entering view
// fire off the "didLoad" lifecycle events
this._didLoad(view);
componentRef.changeDetectorRef.detectChanges();
}
_viewTest(enteringView: ViewController, leavingView: ViewController, ti: TransitionInstruction) {
@ -753,6 +753,12 @@ export class NavControllerBase extends Ion implements NavController {
}
}
_preLoad(view: ViewController) {
assert(this.isTransitioning(), 'nav controller should be transitioning');
view._preLoad();
}
_willLoad(view: ViewController) {
assert(this.isTransitioning(), 'nav controller should be transitioning');

View File

@ -434,6 +434,15 @@ export class ViewController {
/**
* @private
*/
_preLoad() {
this._lifecycle('PreLoad');
}
/**
* @private
* The view has loaded. This event only happens once per view will be created.
* This event is fired before the component and his children have been initialized.
*/
_willLoad() {
this._lifecycle('WillLoad');
}