mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-23 05:58:26 +08:00
@ -202,8 +202,8 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
});
|
||||
}
|
||||
|
||||
// ti.resolve() is called when the navigation transition is finished successfully
|
||||
ti.resolve = (hasCompleted: boolean, isAsync: boolean, enteringName: string, leavingName: string, direction: string) => {
|
||||
// transition has successfully resolved
|
||||
this._trnsId = null;
|
||||
this._init = true;
|
||||
resolve && resolve(hasCompleted, isAsync, enteringName, leavingName, direction);
|
||||
@ -214,23 +214,22 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
this._nextTrns();
|
||||
};
|
||||
|
||||
ti.reject = (rejectReason: any, trns: Transition) => {
|
||||
// rut row raggy, something rejected this transition
|
||||
// ti.reject() is called when the navigation transition fails. ie. it is rejected at some point.
|
||||
ti.reject = (rejectReason: any, transition: Transition) => {
|
||||
this._trnsId = null;
|
||||
this._queue.length = 0;
|
||||
|
||||
while (trns) {
|
||||
if (trns.enteringView && (trns.enteringView._state !== ViewState.LOADED)) {
|
||||
// destroy the entering views and all of their hopes and dreams
|
||||
this._destroyView(trns.enteringView);
|
||||
// walk through the transition views so they are destroyed
|
||||
while (transition) {
|
||||
var enteringView = transition.enteringView;
|
||||
if (enteringView && (enteringView._state === ViewState.ATTACHED)) {
|
||||
this._destroyView(enteringView);
|
||||
}
|
||||
if (!trns.parent) {
|
||||
if (transition.isRoot()) {
|
||||
this._trnsCtrl.destroy(transition.trnsId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (trns) {
|
||||
this._trnsCtrl.destroy(trns.trnsId);
|
||||
transition = transition.parent;
|
||||
}
|
||||
|
||||
reject && reject(false, false, rejectReason);
|
||||
@ -278,7 +277,19 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get entering and leaving views
|
||||
// ensure any of the inserted view are used
|
||||
const insertViews = ti.insertViews;
|
||||
if (insertViews) {
|
||||
for (var i = 0; i < insertViews.length; i++) {
|
||||
var nav = insertViews[i]._nav;
|
||||
if (nav && nav !== this || insertViews[i]._state === ViewState.DESTROYED) {
|
||||
ti.reject('leavingView and enteringView are null. stack is already empty');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// get entering and leaving views
|
||||
const leavingView = this.getActive();
|
||||
const enteringView = this._getEnteringView(ti, leavingView);
|
||||
|
||||
@ -291,7 +302,7 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
this.setTransitioning(true);
|
||||
|
||||
// Initialize enteringView
|
||||
if (enteringView && isBlank(enteringView._state)) {
|
||||
if (enteringView && enteringView._state === ViewState.NEW) {
|
||||
// render the entering view, and all child navs and views
|
||||
// ******** DOM WRITE ****************
|
||||
this._viewInit(enteringView);
|
||||
@ -303,7 +314,6 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
// views have been initialized, now let's test
|
||||
// to see if the transition is even allowed or not
|
||||
return this._viewTest(enteringView, leavingView, ti);
|
||||
|
||||
} else {
|
||||
return this._postViewInit(enteringView, leavingView, ti);
|
||||
}
|
||||
@ -419,7 +429,6 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
// add the views to the
|
||||
for (i = 0; i < insertViews.length; i++) {
|
||||
view = insertViews[i];
|
||||
assert(view, 'view must be non null');
|
||||
this._insertViewAt(view, ti.insertStart + i);
|
||||
}
|
||||
|
||||
@ -477,6 +486,9 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
* DOM WRITE
|
||||
*/
|
||||
_viewInit(enteringView: ViewController) {
|
||||
assert(enteringView, 'enteringView must be non null');
|
||||
assert(enteringView._state === ViewState.NEW, 'enteringView state must be NEW');
|
||||
|
||||
// entering view has not been initialized yet
|
||||
const componentProviders = ReflectiveInjector.resolve([
|
||||
{ provide: NavController, useValue: this },
|
||||
@ -501,7 +513,7 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
// render the component ref instance to the DOM
|
||||
// ******** DOM WRITE ****************
|
||||
viewport.insert(componentRef.hostView, viewport.length);
|
||||
view._state = ViewState.PRE_RENDERED;
|
||||
view._state = ViewState.ATTACHED;
|
||||
|
||||
if (view._cssClass) {
|
||||
// the ElementRef of the actual ion-page created
|
||||
@ -604,14 +616,12 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
}
|
||||
});
|
||||
|
||||
if (enteringView && enteringView._state === ViewState.INITIALIZED) {
|
||||
if (enteringView && (enteringView._state === ViewState.INITIALIZED)) {
|
||||
// render the entering component in the DOM
|
||||
// this would also render new child navs/views
|
||||
// which may have their very own async canEnter/Leave tests
|
||||
// ******** DOM WRITE ****************
|
||||
this._viewAttachToDOM(enteringView, enteringView._cmp, this._viewport);
|
||||
} else {
|
||||
console.debug('enteringView state is not INITIALIZED', enteringView);
|
||||
}
|
||||
|
||||
if (!transition.hasChildren) {
|
||||
@ -762,9 +772,10 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
if (existingIndex > -1) {
|
||||
// this view is already in the stack!!
|
||||
// move it to its new location
|
||||
assert(view._nav === this, 'view is not part of the nav');
|
||||
this._views.splice(index, 0, this._views.splice(existingIndex, 1)[0]);
|
||||
|
||||
} else {
|
||||
assert(!view._nav, 'nav is used');
|
||||
// this is a new view to add to the stack
|
||||
// create the new entering view
|
||||
view._setNav(this);
|
||||
@ -781,6 +792,8 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
}
|
||||
|
||||
_removeView(view: ViewController) {
|
||||
assert(view._state === ViewState.ATTACHED || view._state === ViewState.DESTROYED, 'view state should be loaded or destroyed');
|
||||
|
||||
const views = this._views;
|
||||
const index = views.indexOf(view);
|
||||
assert(index > -1, 'view must be part of the stack');
|
||||
@ -1056,7 +1069,7 @@ export class NavControllerBase extends Ion implements NavController {
|
||||
dismissPageChangeViews() {
|
||||
for (let view of this._views) {
|
||||
if (view.data && view.data.dismissOnPageChange) {
|
||||
view.dismiss();
|
||||
view.dismiss().catch(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -193,9 +193,10 @@ export interface TransitionInstruction {
|
||||
}
|
||||
|
||||
export enum ViewState {
|
||||
INITIALIZED,
|
||||
PRE_RENDERED,
|
||||
LOADED,
|
||||
NEW, // New created ViewController
|
||||
INITIALIZED, // Initialized by the NavController
|
||||
ATTACHED, // Loaded to the DOM
|
||||
DESTROYED // Destroyed by the NavController
|
||||
}
|
||||
|
||||
export const INIT_ZINDEX = 100;
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { mockNavController, mockView, mockViews } from '../../util/mock-providers';
|
||||
|
||||
import { ViewState } from '../nav-util';
|
||||
|
||||
describe('ViewController', () => {
|
||||
|
||||
@ -16,6 +16,7 @@ describe('ViewController', () => {
|
||||
});
|
||||
|
||||
// act
|
||||
viewController._state = ViewState.ATTACHED;
|
||||
viewController._willEnter();
|
||||
}, 10000);
|
||||
});
|
||||
@ -33,6 +34,7 @@ describe('ViewController', () => {
|
||||
});
|
||||
|
||||
// act
|
||||
viewController._state = ViewState.ATTACHED;
|
||||
viewController._didEnter();
|
||||
}, 10000);
|
||||
});
|
||||
@ -50,6 +52,7 @@ describe('ViewController', () => {
|
||||
});
|
||||
|
||||
// act
|
||||
viewController._state = ViewState.ATTACHED;
|
||||
viewController._willLeave(false);
|
||||
}, 10000);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { ComponentRef, ElementRef, EventEmitter, Output, Renderer } from '@angular/core';
|
||||
|
||||
import { Footer, Header } from '../components/toolbar/toolbar';
|
||||
import { isPresent } from '../util/util';
|
||||
import { isPresent, assert } from '../util/util';
|
||||
import { Navbar } from '../components/navbar/navbar';
|
||||
import { NavController } from './nav-controller';
|
||||
import { NavOptions, ViewState } from './nav-util';
|
||||
@ -46,7 +46,7 @@ export class ViewController {
|
||||
_cmp: ComponentRef<any>;
|
||||
_nav: NavController;
|
||||
_zIndex: number;
|
||||
_state: ViewState;
|
||||
_state: ViewState = ViewState.NEW;
|
||||
_cssClass: string;
|
||||
|
||||
/**
|
||||
@ -227,7 +227,7 @@ export class ViewController {
|
||||
* @private
|
||||
*/
|
||||
get name(): string {
|
||||
return this.component ? this.component.name : '';
|
||||
return (this.component ? this.component.name : '');
|
||||
}
|
||||
|
||||
/**
|
||||
@ -261,14 +261,12 @@ export class ViewController {
|
||||
// _hidden value of '' means the hidden attribute will be added
|
||||
// _hidden value of null means the hidden attribute will be removed
|
||||
// doing checks to make sure we only update the DOM when actually needed
|
||||
if (this._cmp) {
|
||||
// if it should render, then the hidden attribute should not be on the element
|
||||
if (shouldShow === this._isHidden) {
|
||||
this._isHidden = !shouldShow;
|
||||
let value = (shouldShow ? null : '');
|
||||
// ******** DOM WRITE ****************
|
||||
renderer.setElementAttribute(this.pageRef().nativeElement, 'hidden', value);
|
||||
}
|
||||
// if it should render, then the hidden attribute should not be on the element
|
||||
if (this._cmp && shouldShow === this._isHidden) {
|
||||
this._isHidden = !shouldShow;
|
||||
let value = (shouldShow ? null : '');
|
||||
// ******** DOM WRITE ****************
|
||||
renderer.setElementAttribute(this.pageRef().nativeElement, 'hidden', value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -411,6 +409,7 @@ export class ViewController {
|
||||
}
|
||||
|
||||
_preLoad() {
|
||||
assert(this._state === ViewState.INITIALIZED, 'view state must be INITIALIZED');
|
||||
this._lifecycle('PreLoad');
|
||||
}
|
||||
|
||||
@ -420,6 +419,7 @@ export class ViewController {
|
||||
* This event is fired before the component and his children have been initialized.
|
||||
*/
|
||||
_willLoad() {
|
||||
assert(this._state === ViewState.INITIALIZED, 'view state must be INITIALIZED');
|
||||
this._lifecycle('WillLoad');
|
||||
}
|
||||
|
||||
@ -432,6 +432,7 @@ export class ViewController {
|
||||
* recommended method to use when a view becomes active.
|
||||
*/
|
||||
_didLoad() {
|
||||
assert(this._state === ViewState.ATTACHED, 'view state must be ATTACHED');
|
||||
this._lifecycle('DidLoad');
|
||||
}
|
||||
|
||||
@ -440,6 +441,8 @@ export class ViewController {
|
||||
* The view is about to enter and become the active view.
|
||||
*/
|
||||
_willEnter() {
|
||||
assert(this._state === ViewState.ATTACHED, 'view state must be ATTACHED');
|
||||
|
||||
if (this._detached && this._cmp) {
|
||||
// ensure this has been re-attached to the change detector
|
||||
this._cmp.changeDetectorRef.reattach();
|
||||
@ -456,6 +459,8 @@ export class ViewController {
|
||||
* will fire, whether it was the first load or loaded from the cache.
|
||||
*/
|
||||
_didEnter() {
|
||||
assert(this._state === ViewState.ATTACHED, 'view state must be ATTACHED');
|
||||
|
||||
this._nb && this._nb.didEnter();
|
||||
this.didEnter.emit(null);
|
||||
this._lifecycle('DidEnter');
|
||||
@ -510,6 +515,8 @@ export class ViewController {
|
||||
* DOM WRITE
|
||||
*/
|
||||
_destroy(renderer: Renderer) {
|
||||
assert(this._state !== ViewState.DESTROYED, 'view state must be ATTACHED');
|
||||
|
||||
if (this._cmp) {
|
||||
if (renderer) {
|
||||
// ensure the element is cleaned up for when the view pool reuses this element
|
||||
@ -524,6 +531,7 @@ export class ViewController {
|
||||
}
|
||||
|
||||
this._nav = this._cmp = this.instance = this._cntDir = this._cntRef = this._leavingOpts = this._hdrDir = this._ftrDir = this._nb = this._onDidDismiss = this._onWillDismiss = null;
|
||||
this._state = ViewState.DESTROYED;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -534,7 +542,7 @@ export class ViewController {
|
||||
const methodName = 'ionViewCan' + lifecycle;
|
||||
if (instance && instance[methodName]) {
|
||||
try {
|
||||
let result = instance[methodName]();
|
||||
var result = instance[methodName]();
|
||||
if (result === false) {
|
||||
return false;
|
||||
} else if (result instanceof Promise) {
|
||||
|
Reference in New Issue
Block a user