From 520fe02914cf31520e35ebf020386713a9caea0a Mon Sep 17 00:00:00 2001 From: vakrilov Date: Wed, 6 Jul 2016 15:31:06 +0300 Subject: [PATCH] PageRoute spike --- .gitignore | 1 + nativescript-angular/router/ns-router-link.ts | 24 +++++---- nativescript-angular/router/ns-router.ts | 1 + .../router/page-router-outlet.ts | 49 +++++++++++++++---- ng-sample/.vscode/launch.json | 4 +- ng-sample/app/app.ts | 6 +-- .../router/page-router-outlet-nested-test.ts | 2 + .../router/page-router-outlet-test.ts | 8 +-- ng-sample/package.json | 2 +- tests/app/tests/snippets.ts | 31 +++++------- 10 files changed, 81 insertions(+), 47 deletions(-) diff --git a/.gitignore b/.gitignore index 33742d38b..26b2edde9 100644 --- a/.gitignore +++ b/.gitignore @@ -16,6 +16,7 @@ nativescript-angular/**/*.js .nvm .vscode .DS_Store +npm-debug.log nativescript-angular*.tgz tests/app/**/*.js diff --git a/nativescript-angular/router/ns-router-link.ts b/nativescript-angular/router/ns-router-link.ts index 9b0af03fb..b176829a5 100644 --- a/nativescript-angular/router/ns-router-link.ts +++ b/nativescript-angular/router/ns-router-link.ts @@ -1,10 +1,10 @@ -import {Directive, HostBinding, HostListener, Input} from '@angular/core'; -import {LocationStrategy} from '@angular/common'; -import {Router, ActivatedRoute, UrlTree} from '@angular/router'; +import {Directive, HostListener, Input, Optional} from '@angular/core'; +import {Router, ActivatedRoute} from '@angular/router'; import {routerLog} from "../trace"; +import {PageRoute} from "./page-router-outlet"; /** - * The RouterLink directive lets you link to specific parts of your app. + * The nsRouterLink directive lets you link to specific parts of your app. * * Consider the following route configuration: @@ -35,10 +35,14 @@ export class NSRouterLink { @Input() queryParams: { [k: string]: any }; @Input() fragment: string; - /** - * @internal - */ - constructor(private router: Router, private route: ActivatedRoute) { } + private usePageRoute: boolean; + +constructor( + private router: Router, + private route: ActivatedRoute, + @Optional() private pageRoute: PageRoute) { + this.usePageRoute = (this.pageRoute && this.route === this.pageRoute.activatedRoute.getValue()); + } @Input("nsRouterLink") set params(data: any[] | string) { @@ -52,8 +56,10 @@ export class NSRouterLink { @HostListener("tap") onTap() { routerLog("nsRouterLink.tapped: " + this.commands); + const currentRoute = this.usePageRoute ? this.pageRoute.activatedRoute.getValue() : this.route; + this.router.navigate( this.commands, - { relativeTo: this.route, queryParams: this.queryParams, fragment: this.fragment }); + { relativeTo: currentRoute, queryParams: this.queryParams, fragment: this.fragment }); } } diff --git a/nativescript-angular/router/ns-router.ts b/nativescript-angular/router/ns-router.ts index 1b93531f6..cacebf84d 100644 --- a/nativescript-angular/router/ns-router.ts +++ b/nativescript-angular/router/ns-router.ts @@ -10,6 +10,7 @@ import {NSLocationStrategy} from './ns-location-strategy'; import {NativescriptPlatformLocation} from './ns-platform-location'; export {routerTraceCategory} from "../trace"; +export {PageRoute} from './page-router-outlet'; export const NS_ROUTER_PROVIDERS: any[] = [ NSLocationStrategy, diff --git a/nativescript-angular/router/page-router-outlet.ts b/nativescript-angular/router/page-router-outlet.ts index a0c3c394a..b4ef01f6c 100644 --- a/nativescript-angular/router/page-router-outlet.ts +++ b/nativescript-angular/router/page-router-outlet.ts @@ -4,9 +4,9 @@ import { Inject, ComponentResolver, provide, ComponentFactoryResolver, NoComponentFactoryError} from '@angular/core'; -import {isBlank, isPresent} from '@angular/core/src/facade/lang'; +import {isPresent} from '@angular/core/src/facade/lang'; -import {RouterOutletMap, ActivatedRoute, RouterOutlet, PRIMARY_OUTLET} from '@angular/router'; +import {RouterOutletMap, ActivatedRoute, PRIMARY_OUTLET} from '@angular/router'; import {NSLocationStrategy} from "./ns-location-strategy"; import {DEVICE} from "../platform-providers"; import {Device} from "platform"; @@ -15,20 +15,35 @@ import {DetachedLoader} from "../common/detached-loader"; import {ViewUtil} from "../view-util"; import {topmost} from "ui/frame"; import {Page, NavigatedData} from "ui/page"; +import {BehaviorSubject} from "rxjs"; interface CacheItem { componentRef: ComponentRef; + reusedRoute: PageRoute; + outletMap: RouterOutletMap; loaderRef?: ComponentRef; } +export class PageRoute { + activatedRoute: BehaviorSubject; + constructor(startRoute: ActivatedRoute) { + this.activatedRoute = new BehaviorSubject(startRoute); + } +} + + /** * Reference Cache */ class RefCache { private cache: Array = new Array(); - public push(comp: ComponentRef, loaderRef?: ComponentRef) { - this.cache.push({ componentRef: comp, loaderRef: loaderRef }); + public push( + componentRef: ComponentRef, + reusedRoute: PageRoute, + outletMap: RouterOutletMap, + loaderRef: ComponentRef) { + this.cache.push({ componentRef, reusedRoute, outletMap, loaderRef }); } public pop(): CacheItem { @@ -125,23 +140,27 @@ export class PageRouterOutlet { this.currentActivatedRoute = activatedRoute; if (this.locationStrategy.isPageNavigatingBack()) { - this.activateOnGoBack(activatedRoute, providers); + this.activateOnGoBack(activatedRoute, providers, outletMap); } else { - this.activateOnGoForward(activatedRoute, providers); + this.activateOnGoForward(activatedRoute, providers, outletMap); } } private activateOnGoForward( activatedRoute: ActivatedRoute, - providers: ResolvedReflectiveProvider[]): void { + providers: ResolvedReflectiveProvider[], + outletMap: RouterOutletMap): void { const factory = this.getComponentFactory(activatedRoute); + const reusedRoute = new PageRoute(activatedRoute); + providers = [...providers, ...ReflectiveInjector.resolve([{ provide: PageRoute, useValue: reusedRoute }])]; + if (this.isInitalPage) { log("PageRouterOutlet.activate() inital page - just load component: " + activatedRoute.component); this.isInitalPage = false; const inj = ReflectiveInjector.fromResolvedProviders(providers, this.containerRef.parentInjector); this.currnetActivatedComp = this.containerRef.createComponent(factory, this.containerRef.length, inj, []); - this.refCache.push(this.currnetActivatedComp, null); + this.refCache.push(this.currnetActivatedComp, reusedRoute, outletMap, null); } else { log("PageRouterOutlet.activate() forward navigation - create detached loader in the loader container: " + activatedRoute.component); @@ -153,18 +172,28 @@ export class PageRouterOutlet { this.currnetActivatedComp = loaderRef.instance.loadWithFactory(factory); this.loadComponentInPage(page, this.currnetActivatedComp); - this.refCache.push(this.currnetActivatedComp, loaderRef); + this.refCache.push(this.currnetActivatedComp, reusedRoute, outletMap, loaderRef); } } private activateOnGoBack( activatedRoute: ActivatedRoute, - providers: ResolvedReflectiveProvider[]): void { + providers: ResolvedReflectiveProvider[], + outletMap: RouterOutletMap): void { log("PageRouterOutlet.activate() - Back naviation, so load from cache: " + activatedRoute.component); this.locationStrategy.finishBackPageNavigation(); let cacheItem = this.refCache.peek(); + cacheItem.reusedRoute.activatedRoute.next(activatedRoute); + + this.outletMap = cacheItem.outletMap; + + // HACK: Fill the outlet map provided by the router, with the outlets that we have cached. + // This is needed beacuse the component is taken form the cache and not created - so it will not register + // its child router-outlets to the newly created outlet map. + Object.assign(outletMap, cacheItem.outletMap); + this.currnetActivatedComp = cacheItem.componentRef; } diff --git a/ng-sample/.vscode/launch.json b/ng-sample/.vscode/launch.json index 2e88384e5..d2ea7615d 100644 --- a/ng-sample/.vscode/launch.json +++ b/ng-sample/.vscode/launch.json @@ -67,7 +67,7 @@ "platform": "android", "request": "attach", "appRoot": "${workspaceRoot}", - "sourceMaps": false, + "sourceMaps": true, "diagnosticLogging": false, "emulator": false }, @@ -77,7 +77,7 @@ "platform": "android", "request": "attach", "appRoot": "${workspaceRoot}", - "sourceMaps": false, + "sourceMaps": true, "diagnosticLogging": false, "emulator": true } diff --git a/ng-sample/app/app.ts b/ng-sample/app/app.ts index 0eb9782c9..23dc01a8d 100644 --- a/ng-sample/app/app.ts +++ b/ng-sample/app/app.ts @@ -15,7 +15,7 @@ import { rendererTraceCategory, routerTraceCategory, listViewTraceCategory } fro import trace = require("trace"); // trace.setCategories(rendererTraceCategory); -// trace.setCategories(routerTraceCategory); +trace.setCategories(routerTraceCategory); // trace.setCategories(listViewTraceCategory); trace.enable(); @@ -53,7 +53,7 @@ import { AnimationStatesTest } from "./examples/animation/animation-states-test" // nativeScriptBootstrap(ListTest); // nativeScriptBootstrap(ListTestAsync); //nativeScriptBootstrap(ImageTest); -nativeScriptBootstrap(HttpTest); +// nativeScriptBootstrap(HttpTest); //nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED], { startPageActionBarHidden: false }); //nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED]); //nativeScriptBootstrap(ModalTest); @@ -62,7 +62,7 @@ nativeScriptBootstrap(HttpTest); // new router // nativeScriptBootstrap(RouterOutletAppComponent, [RouterOutletRouterProviders]); // nativeScriptBootstrap(PageRouterOutletAppComponent, [PageRouterOutletRouterProviders]); -// nativeScriptBootstrap(PageRouterOutletNestedAppComponent, [PageRouterOutletNestedRouterProviders]); +nativeScriptBootstrap(PageRouterOutletNestedAppComponent, [PageRouterOutletNestedRouterProviders]); // router-deprecated // nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS_DEPRECATED]); diff --git a/ng-sample/app/examples/router/page-router-outlet-nested-test.ts b/ng-sample/app/examples/router/page-router-outlet-nested-test.ts index a215438f3..1891435e7 100644 --- a/ng-sample/app/examples/router/page-router-outlet-nested-test.ts +++ b/ng-sample/app/examples/router/page-router-outlet-nested-test.ts @@ -85,6 +85,8 @@ class DetailComponent { + + diff --git a/ng-sample/app/examples/router/page-router-outlet-test.ts b/ng-sample/app/examples/router/page-router-outlet-test.ts index 5be6b37ec..57028ec8b 100644 --- a/ng-sample/app/examples/router/page-router-outlet-test.ts +++ b/ng-sample/app/examples/router/page-router-outlet-test.ts @@ -1,8 +1,8 @@ import { Component, OnInit, OnDestroy } from "@angular/core"; -import { RouterConfig, ActivatedRoute, Router, ROUTER_DIRECTIVES, Event } from '@angular/router'; +import { RouterConfig, ActivatedRoute, Router, ROUTER_DIRECTIVES } from '@angular/router'; import { Observable } from "rxjs"; -import { NS_ROUTER_DIRECTIVES, nsProvideRouter} from "nativescript-angular/router" -import { Location, LocationStrategy} from '@angular/common'; +import { NS_ROUTER_DIRECTIVES, nsProvideRouter} from "nativescript-angular/router"; +import { Location } from '@angular/common'; import { Page } from "ui/page"; @@ -113,7 +113,7 @@ export class PageRouterOutletAppComponent { constructor(router: Router, private location: Location) { router.events.subscribe((e) => { console.log("--EVENT-->: " + e.toString()); - }) + }); } } diff --git a/ng-sample/package.json b/ng-sample/package.json index faacefc79..1093214bb 100644 --- a/ng-sample/package.json +++ b/ng-sample/package.json @@ -60,7 +60,7 @@ "version": "2.1.1" }, "tns-ios": { - "version": "2.1.0" + "version": "2.1.1" } } } \ No newline at end of file diff --git a/tests/app/tests/snippets.ts b/tests/app/tests/snippets.ts index 836aaa496..feb49cfa7 100644 --- a/tests/app/tests/snippets.ts +++ b/tests/app/tests/snippets.ts @@ -1,8 +1,7 @@ //make sure you import mocha-config before @angular/core import {assert} from "./test-config"; -import {Component, ElementRef, Renderer} from "@angular/core"; -import {NavigationEnd, NavigationStart, NavigationError} from "@angular/router"; +import {NavigationEnd, NavigationStart} from "@angular/router"; import {Subscription} from "rxjs"; import {TestApp, bootstrapTestApp, destroyTestApp} from "./test-app"; @@ -24,7 +23,7 @@ describe('Snippets', () => { before(() => { return TestApp.create().then((app) => { testApp = app; - }) + }); }); after(() => { @@ -54,13 +53,13 @@ describe('Snippets', () => { setTimeout(done, 10); }); }); -}) +}); describe('Snippets Navigation', () => { - var runningApp: any; - var subscription: Subscription; + let runningApp: any; + let subscription: Subscription; - var cleanup = () => { + const cleanup = () => { if (subscription) { subscription.unsubscribe(); subscription = null; @@ -69,15 +68,14 @@ describe('Snippets Navigation', () => { destroyTestApp(runningApp); runningApp = null; } - } + }; after(cleanup); it("router-outlet app", (done) => { bootstrapTestApp(NavigationApp, [APP_ROUTER_PROVIDERS]).then((app) => { - console.log("app bootstraped"); runningApp = app; - var navStarted = false; + let navStarted = false; subscription = app.router.events.subscribe((e) => { if (e instanceof NavigationStart) { @@ -92,17 +90,14 @@ describe('Snippets Navigation', () => { cleanup(); done(); } - }) - }) + }); + }); }); it("page-router-outlet app", (done) => { - console.log("------------- PageNavigationApp: " + PageNavigationApp); - bootstrapTestApp(PageNavigationApp, [APP_ROUTER_PROVIDERS]).then((app) => { - console.log("app bootstraped"); runningApp = app; - var navStarted = false; + let navStarted = false; subscription = app.router.events.subscribe((e) => { if (e instanceof NavigationStart) { @@ -117,7 +112,7 @@ describe('Snippets Navigation', () => { cleanup(); done(); } - }) - }) + }); + }); }); }); \ No newline at end of file