diff --git a/src/components/nav/nav.ts b/src/components/nav/nav.ts index 1f8318d018..aa6224ec33 100644 --- a/src/components/nav/nav.ts +++ b/src/components/nav/nav.ts @@ -1,4 +1,4 @@ -import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, forwardRef, Input, Optional, NgZone, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core'; +import { AfterViewInit, Component, ComponentFactoryResolver, ElementRef, ErrorHandler, forwardRef, Input, Optional, NgZone, Renderer, ViewChild, ViewContainerRef, ViewEncapsulation } from '@angular/core'; import { App } from '../app/app'; import { Config } from '../../config/config'; @@ -74,8 +74,9 @@ export class Nav extends NavControllerBase implements AfterViewInit, RootNode { transCtrl: TransitionController, @Optional() linker: DeepLinker, domCtrl: DomController, + errHandler: ErrorHandler ) { - super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl); + super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler); if (viewCtrl) { // an ion-nav can also act as an ion-page within a parent ion-nav diff --git a/src/components/nav/overlay-portal.ts b/src/components/nav/overlay-portal.ts index 74f68cdb12..d81a9f5a2c 100644 --- a/src/components/nav/overlay-portal.ts +++ b/src/components/nav/overlay-portal.ts @@ -1,4 +1,4 @@ -import { ComponentFactoryResolver, Directive, ElementRef, forwardRef, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef } from '@angular/core'; +import { ComponentFactoryResolver, Directive, ElementRef, ErrorHandler, forwardRef, Inject, Input, NgZone, Optional, Renderer, ViewContainerRef } from '@angular/core'; import { App } from '../app/app'; import { Config } from '../../config/config'; @@ -31,8 +31,9 @@ export class OverlayPortal extends NavControllerBase { @Optional() linker: DeepLinker, viewPort: ViewContainerRef, domCtrl: DomController, + errHandler: ErrorHandler ) { - super(null, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl); + super(null, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, domCtrl, errHandler); this._isPortal = true; this._init = true; this.setViewport(viewPort); diff --git a/src/components/nav/test/nav.spec.ts b/src/components/nav/test/nav.spec.ts index 109aa98e19..075213abdb 100644 --- a/src/components/nav/test/nav.spec.ts +++ b/src/components/nav/test/nav.spec.ts @@ -109,7 +109,8 @@ function getNav() { gestureCtrl, trnsCtrl, linker, - dom + dom, + null ); return nav; } diff --git a/src/components/tabs/tab.ts b/src/components/tabs/tab.ts index a2e93136a0..e9b5f7e63d 100644 --- a/src/components/tabs/tab.ts +++ b/src/components/tabs/tab.ts @@ -1,4 +1,4 @@ -import { ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, ElementRef, EventEmitter, Input, NgZone, Optional, Output, Renderer, ViewChild, ViewEncapsulation, ViewContainerRef } from '@angular/core'; +import { ChangeDetectorRef, Component, ComponentFactoryResolver, ComponentRef, ElementRef, ErrorHandler, EventEmitter, Input, NgZone, Optional, Output, Renderer, ViewChild, ViewEncapsulation, ViewContainerRef } from '@angular/core'; import { App } from '../app/app'; import { Config } from '../../config/config'; @@ -264,9 +264,10 @@ export class Tab extends NavControllerBase { transCtrl: TransitionController, @Optional() private linker: DeepLinker, private _dom: DomController, + errHandler: ErrorHandler ) { // A Tab is a NavController for its child pages - super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, _dom); + super(parent, app, config, plt, keyboard, elementRef, zone, renderer, cfr, gestureCtrl, transCtrl, linker, _dom, errHandler); this.id = parent.add(this); this._tabsHideOnSubPages = config.getBoolean('tabsHideOnSubPages'); diff --git a/src/navigation/nav-controller-base.ts b/src/navigation/nav-controller-base.ts index 25057eead9..e57f2115d4 100644 --- a/src/navigation/nav-controller-base.ts +++ b/src/navigation/nav-controller-base.ts @@ -1,4 +1,4 @@ -import { ComponentRef, Input, ComponentFactoryResolver, ElementRef, EventEmitter, NgZone, ReflectiveInjector, Renderer, ViewContainerRef } from '@angular/core'; +import { ComponentRef, Input, ComponentFactoryResolver, ElementRef, ErrorHandler, EventEmitter, NgZone, ReflectiveInjector, Renderer, ViewContainerRef } from '@angular/core'; import { AnimationOptions } from '../animations/animation'; import { App } from '../components/app/app'; @@ -71,7 +71,8 @@ export class NavControllerBase extends Ion implements NavController { public _gestureCtrl: GestureController, public _trnsCtrl: TransitionController, public _linker: DeepLinker, - private _domCtrl: DomController + private _domCtrl: DomController, + private _errHandler: ErrorHandler ) { super(config, elementRef, renderer); @@ -350,7 +351,7 @@ export class NavControllerBase extends Ion implements NavController { if (nav && nav !== this) { throw 'inserted view was already inserted'; } - if (viewControllers[i]._state === STATE_DESTROYED) { + if (view._state === STATE_DESTROYED) { throw 'inserted view was already destroyed'; } } @@ -857,61 +858,89 @@ export class NavControllerBase extends Ion implements NavController { _willLoad(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); - view._willLoad(); + try { + view._willLoad(); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _didLoad(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._didLoad(); - this.viewDidLoad.emit(view); - this._app.viewDidLoad.emit(view); + try { + view._didLoad(); + this.viewDidLoad.emit(view); + this._app.viewDidLoad.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _willEnter(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._willEnter(); - this.viewWillEnter.emit(view); - this._app.viewWillEnter.emit(view); + try { + view._willEnter(); + this.viewWillEnter.emit(view); + this._app.viewWillEnter.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _didEnter(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._didEnter(); - this.viewDidEnter.emit(view); - this._app.viewDidEnter.emit(view); + try { + view._didEnter(); + this.viewDidEnter.emit(view); + this._app.viewDidEnter.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _willLeave(view: ViewController, willUnload: boolean) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._willLeave(willUnload); - this.viewWillLeave.emit(view); - this._app.viewWillLeave.emit(view); + try { + view._willLeave(willUnload); + this.viewWillLeave.emit(view); + this._app.viewWillLeave.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _didLeave(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._didLeave(); - this.viewDidLeave.emit(view); - this._app.viewDidLeave.emit(view); + try { + view._didLeave(); + this.viewDidLeave.emit(view); + this._app.viewDidLeave.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } _willUnload(view: ViewController) { assert(this.isTransitioning(), 'nav controller should be transitioning'); assert(NgZone.isInAngularZone(), 'callback should be zoned'); - view._willUnload(); - this.viewWillUnload.emit(view); - this._app.viewWillUnload.emit(view); + try { + view._willUnload(); + this.viewWillUnload.emit(view); + this._app.viewWillUnload.emit(view); + } catch (e) { + this._errHandler && this._errHandler.handleError(e); + } } hasChildren(): boolean { diff --git a/src/navigation/view-controller.ts b/src/navigation/view-controller.ts index 4996028c93..bf900119ed 100644 --- a/src/navigation/view-controller.ts +++ b/src/navigation/view-controller.ts @@ -105,7 +105,11 @@ export class ViewController { /** @hidden */ @Output() private _emitter: EventEmitter = new EventEmitter(); - constructor(public component?: any, data?: any, rootCssClass: string = DEFAULT_CSS_CLASS) { + constructor( + public component?: any, + data?: any, + rootCssClass: string = DEFAULT_CSS_CLASS + ) { // passed in data could be NavParams, but all we care about is its data object this.data = (data instanceof NavParams ? data.data : (isPresent(data) ? data : {})); @@ -541,7 +545,7 @@ export class ViewController { /** * @hidden */ - _lifecycleTest(lifecycle: string): Promise { + _lifecycleTest(lifecycle: string): Promise { const instance = this.instance; const methodName = 'ionViewCan' + lifecycle; if (instance && instance[methodName]) { @@ -561,16 +565,14 @@ export class ViewController { return Promise.resolve(true); } + /** + * @hidden + */ _lifecycle(lifecycle: string) { const instance = this.instance; const methodName = 'ionView' + lifecycle; if (instance && instance[methodName]) { - try { - instance[methodName](); - - } catch (e) { - console.error(`${this.name} ${methodName} error: ${e.message}`); - } + instance[methodName](); } } diff --git a/src/util/mock-providers.ts b/src/util/mock-providers.ts index 5fdb22f269..b92eafe733 100644 --- a/src/util/mock-providers.ts +++ b/src/util/mock-providers.ts @@ -423,7 +423,8 @@ export function mockNavController(): NavControllerBase { gestureCtrl, trnsCtrl, linker, - dom + dom, + null ); nav._viewInit = function(enteringView: ViewController) { @@ -468,7 +469,8 @@ export function mockOverlayPortal(app: App, config: Config, plt: MockPlatform): null, deepLinker, null, - dom + dom, + null ); } @@ -500,7 +502,8 @@ export function mockTab(parentTabs: Tabs): Tab { gestureCtrl, null, linker, - dom + dom, + null ); tab.load = (opts: any, cb: Function) => {