From 9094c66f3d467718e1372335c602bce7c77f7119 Mon Sep 17 00:00:00 2001 From: "Manu Mtz.-Almeida" Date: Tue, 20 Mar 2018 18:52:12 +0100 Subject: [PATCH] fix(angular): ion-nav no routing --- angular/src/navigation/ion-nav.ts | 46 +++--------- angular/src/providers/angular-delegate.ts | 6 +- core/src/components.d.ts | 4 + core/src/components/nav/nav.tsx | 40 +++++----- core/src/components/nav/readme.md | 10 +++ core/src/components/nav/view-controller.ts | 4 +- demos/angular/src/app/app-routing.module.ts | 3 + .../no-routing-nav-routing.module.ts | 14 ++++ .../no-routing-nav.component.ts | 20 +++++ .../no-routing-nav/no-routing-nav.module.ts | 31 ++++++++ .../src/app/no-routing-nav/pages/page-one.ts | 62 ++++++++++++++++ .../app/no-routing-nav/pages/page-three.ts | 63 ++++++++++++++++ .../src/app/no-routing-nav/pages/page-two.ts | 73 +++++++++++++++++++ 13 files changed, 318 insertions(+), 58 deletions(-) create mode 100755 demos/angular/src/app/no-routing-nav/no-routing-nav-routing.module.ts create mode 100755 demos/angular/src/app/no-routing-nav/no-routing-nav.component.ts create mode 100755 demos/angular/src/app/no-routing-nav/no-routing-nav.module.ts create mode 100755 demos/angular/src/app/no-routing-nav/pages/page-one.ts create mode 100755 demos/angular/src/app/no-routing-nav/pages/page-three.ts create mode 100755 demos/angular/src/app/no-routing-nav/pages/page-two.ts diff --git a/angular/src/navigation/ion-nav.ts b/angular/src/navigation/ion-nav.ts index 30dbabe0594..449cfe835d5 100644 --- a/angular/src/navigation/ion-nav.ts +++ b/angular/src/navigation/ion-nav.ts @@ -1,7 +1,6 @@ import { ComponentFactoryResolver, Directive, ElementRef, Injector} from '@angular/core'; -import { NavigationEnd, NavigationStart, Router } from '@angular/router'; -import { FrameworkDelegate, NavOptions, NavParams, TransitionDoneFn, ViewController } from '@ionic/core'; +import { NavOptions, NavParams, TransitionDoneFn, ViewController } from '@ionic/core'; import { proxyEl } from '../util/util'; import { AngularDelegate } from '..'; @@ -11,50 +10,37 @@ import { AngularDelegate } from '..'; }) export class IonNav { - private delegate: FrameworkDelegate; - constructor( private ref: ElementRef, - router: Router, cfr: ComponentFactoryResolver, injector: Injector, angularDelegate: AngularDelegate, ) { - this.delegate = angularDelegate.create(cfr, injector); - console.log('ion-nav'); - - router.events.subscribe(ev => { - if (ev instanceof NavigationStart) { - console.log('NavigationStart', ev.url); - - } else if (ev instanceof NavigationEnd) { - console.log('NavigationEnd', ev.url); - } - }); + this.ref.nativeElement.delegate = angularDelegate.create(cfr, injector); } push(page: any, params?: NavParams, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'push', page, params, this.wrap(opts), done); + return proxyEl(this.ref, 'push', page, params, opts, done); } insert(insertIndex: number, page: any, params?: NavParams, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'insert', insertIndex, page, params, this.wrap(opts), done); + return proxyEl(this.ref, 'insert', insertIndex, page, params, opts, done); } insertPages(insertIndex: number, insertPages: any[], opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'insertPages', insertIndex, insertPages, this.wrap(opts), done); + return proxyEl(this.ref, 'insertPages', insertIndex, insertPages, opts, done); } pop(opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'pop', this.wrap(opts), done); + return proxyEl(this.ref, 'pop', opts, done); } popTo(indexOrViewCtrl: any, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'popTo', indexOrViewCtrl, this.wrap(opts), done); + return proxyEl(this.ref, 'popTo', indexOrViewCtrl, opts, done); } popToRoot(opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'popToRoot', this.wrap(opts), done); + return proxyEl(this.ref, 'popToRoot', opts, done); } popAll(): Promise { @@ -62,19 +48,19 @@ export class IonNav { } removeIndex(startIndex: number, removeCount = 1, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'removeIndex', startIndex, removeCount, this.wrap(opts), done); + return proxyEl(this.ref, 'removeIndex', startIndex, removeCount, opts, done); } removeView(viewController: ViewController, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'removeView', viewController, this.wrap(opts), done); + return proxyEl(this.ref, 'removeView', viewController, opts, done); } setRoot(pageOrViewCtrl: any, params?: any, opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'setRoot', pageOrViewCtrl, params, this.wrap(opts), done); + return proxyEl(this.ref, 'setRoot', pageOrViewCtrl, params, opts, done); } setPages(pages: any[], opts?: NavOptions, done?: TransitionDoneFn): Promise { - return proxyEl(this.ref, 'setPages', pages, this.wrap(opts), done); + return proxyEl(this.ref, 'setPages', pages, opts, done); } getAllChildNavs(): any[] { @@ -114,12 +100,4 @@ export class IonNav { length() { return proxyEl(this.ref, 'length'); } - - private wrap(opts?: NavOptions): NavOptions { - return { - ...this.wrap(opts), - delegate: this.delegate - }; - } - } diff --git a/angular/src/providers/angular-delegate.ts b/angular/src/providers/angular-delegate.ts index a41a4fb504c..9fd6328a7d8 100644 --- a/angular/src/providers/angular-delegate.ts +++ b/angular/src/providers/angular-delegate.ts @@ -53,9 +53,9 @@ export class AngularFrameworkDelegate implements FrameworkDelegate { } removeViewFromDom(_container: any, component: any): Promise { - const mountingData = this.elRefMap.get(component); - if (mountingData) { - mountingData.componentRef.destroy(); + const componentRef = this.elRefMap.get(component); + if (componentRef) { + componentRef.destroy(); this.elRefMap.delete(component); } return Promise.resolve(); diff --git a/core/src/components.d.ts b/core/src/components.d.ts index 6b005666f21..412f2def43d 100644 --- a/core/src/components.d.ts +++ b/core/src/components.d.ts @@ -42,6 +42,9 @@ import { import { Side, } from './utils/helpers'; +import { + FrameworkDelegate as FrameworkDelegate2, +} from '.'; import { PickerButton, PickerColumn as PickerColumn2, @@ -2010,6 +2013,7 @@ declare global { namespace JSXElements { export interface IonNavAttributes extends HTMLAttributes { animated?: boolean; + delegate?: FrameworkDelegate; root?: any; rootParams?: any; swipeBackEnabled?: boolean; diff --git a/core/src/components/nav/nav.tsx b/core/src/components/nav/nav.tsx index 0f756c358b0..215b8133056 100644 --- a/core/src/components/nav/nav.tsx +++ b/core/src/components/nav/nav.tsx @@ -12,7 +12,7 @@ import { } from './nav-util'; import { ViewController, isViewController } from './view-controller'; -import { Animation, Config, DomController, GestureDetail, NavOutlet } from '../..'; +import { Animation, Config, DomController, FrameworkDelegate, GestureDetail, NavOutlet } from '../..'; import { RouteID, RouteWrite } from '../router/utils/interfaces'; import { assert } from '../../utils/helpers'; @@ -51,6 +51,7 @@ export class NavControllerBase implements NavOutlet { @Prop({ connect: 'ion-animation-controller' }) animationCtrl: HTMLIonAnimationControllerElement; @Prop({ mutable: true }) swipeBackEnabled: boolean; @Prop({ mutable: true }) animated: boolean; + @Prop() delegate: FrameworkDelegate; @Prop() rootParams: any; @Prop() root: any; @Watch('root') @@ -342,16 +343,11 @@ export class NavControllerBase implements NavOutlet { } this._init = true; - // ensure we're not transitioning here - this.isTransitioning = false; - // let's see if there's another to kick off - this._nextTrns(); const isPop = result.direction === NavDirection.back; if (this.useRouter) { const router = document.querySelector('ion-router'); router && router.navChanged(isPop); } - this.ionNavChanged.emit({isPop}); if (ti.done) { @@ -372,11 +368,6 @@ export class NavControllerBase implements NavOutlet { return; } this._queue.length = 0; - - // let's see if there's another to kick off - this.isTransitioning = false; - this._nextTrns(); - this._fireError(rejectReason, ti); } @@ -405,11 +396,16 @@ export class NavControllerBase implements NavOutlet { return false; } - // set that this nav is actively transitioning - this.isTransitioning = true; + this.runTransition(ti); + return true; + } + private async runTransition(ti: TransitionInstruction) { try { + // set that this nav is actively transitioning + this.isTransitioning = true; this._prepareTI(ti); + const leavingView = this.getActive(); const enteringView = this._getEnteringView(ti, leavingView); @@ -421,23 +417,28 @@ export class NavControllerBase implements NavOutlet { ti.requiresTransition = (ti.enteringRequiresTransition || ti.leavingRequiresTransition) && enteringView !== leavingView; if (enteringView && enteringView._state === ViewState.New) { - enteringView.init(this.el); + await enteringView.init(this.el); } this._postViewInit(enteringView, leavingView, ti); - this._transition(enteringView, leavingView, ti) - .then((result) => this._success(result, ti)) - .catch((rejectReason) => this._failed(rejectReason, ti)); + const result = await this._transition(enteringView, leavingView, ti); + this._success(result, ti); } catch (rejectReason) { this._failed(rejectReason, ti); } - return true; + this.isTransitioning = false; + this._nextTrns(); } private _prepareTI(ti: TransitionInstruction) { const viewsLength = this._views.length; + ti.opts = ti.opts || {}; + + if (ti.opts.delegate === undefined) { + ti.opts.delegate = this.delegate; + } if (ti.removeView != null) { assert(isPresent(ti.removeStart), 'removeView needs removeStart'); assert(isPresent(ti.removeCount), 'removeView needs removeCount'); @@ -481,6 +482,7 @@ export class NavControllerBase implements NavOutlet { // Check all the inserted view are correct for (let i = 0; i < viewControllers.length; i++) { const view = viewControllers[i]; + view.delegate = ti.opts.delegate; const nav = view._nav; if (nav && nav !== this) { throw new Error('inserted view was already inserted'); @@ -519,7 +521,7 @@ export class NavControllerBase implements NavOutlet { assert(ti.resolve, 'resolve must be valid'); assert(ti.reject, 'reject must be valid'); - const opts = ti.opts = ti.opts || {}; + const opts = ti.opts; const insertViews = ti.insertViews; const removeStart = ti.removeStart; const removeCount = ti.removeCount; diff --git a/core/src/components/nav/readme.md b/core/src/components/nav/readme.md index 91ddbea7ff2..b90140b7593 100644 --- a/core/src/components/nav/readme.md +++ b/core/src/components/nav/readme.md @@ -12,6 +12,11 @@ boolean +#### delegate + + + + #### root any @@ -34,6 +39,11 @@ boolean boolean +#### delegate + + + + #### root any diff --git a/core/src/components/nav/view-controller.ts b/core/src/components/nav/view-controller.ts index 6ce9b28781b..3ec786961ec 100644 --- a/core/src/components/nav/view-controller.ts +++ b/core/src/components/nav/view-controller.ts @@ -32,11 +32,11 @@ export class ViewController { /** @hidden */ id: string; element: HTMLElement; + delegate: FrameworkDelegate; constructor( public component: any, - public data: any, - private delegate?: FrameworkDelegate, + public data: any ) {} /** diff --git a/demos/angular/src/app/app-routing.module.ts b/demos/angular/src/app/app-routing.module.ts index 41ea04bdbb8..72460e7956f 100644 --- a/demos/angular/src/app/app-routing.module.ts +++ b/demos/angular/src/app/app-routing.module.ts @@ -19,6 +19,9 @@ const routes: Routes = [ { path: 'popover', loadChildren: 'app/popover/popover.module#PopoverModule' }, { path: 'segment', loadChildren: 'app/segment/segment.module#SegmentModule' }, { path: 'virtual-scroll', loadChildren: 'app/virtual-scroll/virtual-scroll.module#VirtualScrollModule' }, + + { path: 'no-routing-nav', loadChildren: 'app/no-routing-nav/no-routing-nav.module#NoRoutingNavModule' }, + ]; @NgModule({ diff --git a/demos/angular/src/app/no-routing-nav/no-routing-nav-routing.module.ts b/demos/angular/src/app/no-routing-nav/no-routing-nav-routing.module.ts new file mode 100755 index 00000000000..b3f29924c2b --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/no-routing-nav-routing.module.ts @@ -0,0 +1,14 @@ +import { NgModule } from '@angular/core'; +import { Routes, RouterModule } from '@angular/router'; + +import { NoRoutingNavPageComponent } from './no-routing-nav.component'; + +const routes: Routes = [ + { path: '', component: NoRoutingNavPageComponent } +]; + +@NgModule({ + imports: [RouterModule.forChild(routes)], + exports: [RouterModule] +}) +export class NoRoutingNavRoutingModule { } diff --git a/demos/angular/src/app/no-routing-nav/no-routing-nav.component.ts b/demos/angular/src/app/no-routing-nav/no-routing-nav.component.ts new file mode 100755 index 00000000000..fad50d57106 --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/no-routing-nav.component.ts @@ -0,0 +1,20 @@ +import { Component } from '@angular/core'; + +import { PageOne } from './pages/page-one'; + +@Component({ + selector: 'app-nav-page', + template: ` + + + + ` +}) +export class NoRoutingNavPageComponent { + + pageOne: any = PageOne; + constructor() { + + } + +} diff --git a/demos/angular/src/app/no-routing-nav/no-routing-nav.module.ts b/demos/angular/src/app/no-routing-nav/no-routing-nav.module.ts new file mode 100755 index 00000000000..0bf72336732 --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/no-routing-nav.module.ts @@ -0,0 +1,31 @@ +import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core'; +import { CommonModule } from '@angular/common'; + +import { NoRoutingNavPageComponent } from './no-routing-nav.component'; +import { NoRoutingNavRoutingModule } from './no-routing-nav-routing.module'; +import { IonicAngularModule } from '@ionic/angular'; + +import { PageOne } from './pages/page-one'; +import { PageTwo } from './pages/page-two'; +import { PageThree } from './pages/page-three'; + +@NgModule({ + imports: [ + CommonModule, + NoRoutingNavRoutingModule, + IonicAngularModule, + ], + declarations: [ + NoRoutingNavPageComponent, + PageOne, + PageTwo, + PageThree + ], + entryComponents: [ + PageOne, + PageTwo, + PageThree + ], + schemas: [CUSTOM_ELEMENTS_SCHEMA] +}) +export class NoRoutingNavModule { } diff --git a/demos/angular/src/app/no-routing-nav/pages/page-one.ts b/demos/angular/src/app/no-routing-nav/pages/page-one.ts new file mode 100755 index 00000000000..802c871bb09 --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/pages/page-one.ts @@ -0,0 +1,62 @@ +import { Component } from '@angular/core'; + +import { PageTwo } from './page-two'; + +@Component({ + selector: 'page-one', + template: ` + + + Page One + + + + Page One +
+ Go to Page Two +
+
    +
  • ngOnInit - {{ngOnInitDetection}}
  • +
  • ionViewWillEnter - {{ionViewWillEnterDetection}}
  • +
  • ionViewDidEnter - {{ionViewDidEnterDetection}}
  • +
+
+ ` +}) +export class PageOne { + + ngOnInitDetection = 'initial'; + ionViewWillEnterDetection = 'initial'; + ionViewDidEnterDetection = 'initial'; + + constructor() { + + } + + + ngOnInit() { + console.log('page one ngOnInit'); + setInterval(() => { + this.ngOnInitDetection = '' + Date.now(); + }, 500); + } + + ionViewWillEnter() { + console.log('page one ionViewWillEnter'); + setInterval(() => { + this.ionViewWillEnterDetection = '' + Date.now(); + }, 500); + } + + ionViewDidEnter() { + console.log('page one ionViewDidEnter'); + setInterval(() => { + this.ionViewDidEnterDetection = '' + Date.now(); + }, 500); + } + + goToPageTwo() { + const nav = document.querySelector('ion-nav') as any; + nav.push(PageTwo).then(() => console.log('push complete')); + } +} diff --git a/demos/angular/src/app/no-routing-nav/pages/page-three.ts b/demos/angular/src/app/no-routing-nav/pages/page-three.ts new file mode 100755 index 00000000000..08e82dacacb --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/pages/page-three.ts @@ -0,0 +1,63 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'page-three', + template: ` + + + + + + Page Three + + + + Page Three +
+ Go Back +
+
    +
  • ngOnInit - {{ngOnInitDetection}}
  • +
  • ionViewWillEnter - {{ionViewWillEnterDetection}}
  • +
  • ionViewDidEnter - {{ionViewDidEnterDetection}}
  • +
+
+ ` +}) +export class PageThree { + + ngOnInitDetection = 'initial'; + ionViewWillEnterDetection = 'initial'; + ionViewDidEnterDetection = 'initial'; + + constructor() { + + } + + + ngOnInit() { + console.log('page two ngOnInit'); + setInterval(() => { + this.ngOnInitDetection = '' + Date.now(); + }, 500); + } + + ionViewWillEnter() { + console.log('page two ionViewWillEnter'); + setInterval(() => { + this.ionViewWillEnterDetection = '' + Date.now(); + }, 500); + } + + ionViewDidEnter() { + console.log('page two ionViewDidEnter'); + setInterval(() => { + this.ionViewDidEnterDetection = '' + Date.now(); + }, 500); + } + + goBack() { + const nav = document.querySelector('ion-nav') as any; + nav.pop().then(() => console.log('pop complete')); + } +} diff --git a/demos/angular/src/app/no-routing-nav/pages/page-two.ts b/demos/angular/src/app/no-routing-nav/pages/page-two.ts new file mode 100755 index 00000000000..d10937e5ae6 --- /dev/null +++ b/demos/angular/src/app/no-routing-nav/pages/page-two.ts @@ -0,0 +1,73 @@ +import { Component } from '@angular/core'; + +import { PageThree } from './page-three'; + +@Component({ + selector: 'page-two', + template: ` + + + + + + Page Two + + + + Page Two +
+ Go to Page Three +
+
+ Go Back +
+
    +
  • ngOnInit - {{ngOnInitDetection}}
  • +
  • ionViewWillEnter - {{ionViewWillEnterDetection}}
  • +
  • ionViewDidEnter - {{ionViewDidEnterDetection}}
  • +
+
+ ` +}) +export class PageTwo { + + ngOnInitDetection = 'initial'; + ionViewWillEnterDetection = 'initial'; + ionViewDidEnterDetection = 'initial'; + + constructor() { + + } + + + ngOnInit() { + console.log('page two ngOnInit'); + setInterval(() => { + this.ngOnInitDetection = '' + Date.now(); + }, 500); + } + + ionViewWillEnter() { + console.log('page two ionViewWillEnter'); + setInterval(() => { + this.ionViewWillEnterDetection = '' + Date.now(); + }, 500); + } + + ionViewDidEnter() { + console.log('page two ionViewDidEnter'); + setInterval(() => { + this.ionViewDidEnterDetection = '' + Date.now(); + }, 500); + } + + goNext() { + const nav = document.querySelector('ion-nav') as any; + nav.push(PageThree).then(() => console.log('push complete')); + } + + goBack() { + const nav = document.querySelector('ion-nav') as any; + nav.pop().then(() => console.log('pop complete')); + } +}