Skip to content

PageRoute #355

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ nativescript-angular/**/*.js
.nvm
.vscode
.DS_Store
npm-debug.log
nativescript-angular*.tgz

tests/app/**/*.js
Expand Down
24 changes: 15 additions & 9 deletions nativescript-angular/router/ns-router-link.ts
Original file line number Diff line number Diff line change
@@ -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:

Expand Down Expand Up @@ -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) {
Expand All @@ -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 });
}
}
1 change: 1 addition & 0 deletions nativescript-angular/router/ns-router.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
49 changes: 39 additions & 10 deletions nativescript-angular/router/page-router-outlet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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<any>;
reusedRoute: PageRoute;
outletMap: RouterOutletMap;
loaderRef?: ComponentRef<any>;
}

export class PageRoute {
activatedRoute: BehaviorSubject<ActivatedRoute>;
constructor(startRoute: ActivatedRoute) {
this.activatedRoute = new BehaviorSubject(startRoute);
}
}


/**
* Reference Cache
*/
class RefCache {
private cache: Array<CacheItem> = new Array<CacheItem>();

public push(comp: ComponentRef<any>, loaderRef?: ComponentRef<any>) {
this.cache.push({ componentRef: comp, loaderRef: loaderRef });
public push(
componentRef: ComponentRef<any>,
reusedRoute: PageRoute,
outletMap: RouterOutletMap,
loaderRef: ComponentRef<any>) {
this.cache.push({ componentRef, reusedRoute, outletMap, loaderRef });
}

public pop(): CacheItem {
Expand Down Expand Up @@ -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);
Expand All @@ -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;
}

Expand Down
4 changes: 2 additions & 2 deletions ng-sample/.vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@
"platform": "android",
"request": "attach",
"appRoot": "${workspaceRoot}",
"sourceMaps": false,
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": false
},
Expand All @@ -77,7 +77,7 @@
"platform": "android",
"request": "attach",
"appRoot": "${workspaceRoot}",
"sourceMaps": false,
"sourceMaps": true,
"diagnosticLogging": false,
"emulator": true
}
Expand Down
6 changes: 3 additions & 3 deletions ng-sample/app/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down Expand Up @@ -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);
Expand All @@ -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]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ class DetailComponent {
<StackLayout>
<Label [text]="'Second component: ' + (depth$ | async)" class="title"></Label>

<Button class="link" text="Nav to First" [nsRouterLink]="['/']"></Button>

<StackLayout class="nav">
<Button class="link" text="< BACK" (tap)="goBack()"></Button>
<Button class="link" [text]="'Second ' + (nextDepth$ | async) + ' >'" [nsRouterLink]="['/second', (nextDepth$ | async)]"></Button>
Expand Down
8 changes: 4 additions & 4 deletions ng-sample/app/examples/router/page-router-outlet-test.ts
Original file line number Diff line number Diff line change
@@ -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";


Expand Down Expand Up @@ -113,7 +113,7 @@ export class PageRouterOutletAppComponent {
constructor(router: Router, private location: Location) {
router.events.subscribe((e) => {
console.log("--EVENT-->: " + e.toString());
})
});
}
}

Expand Down
2 changes: 1 addition & 1 deletion ng-sample/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
"version": "2.1.1"
},
"tns-ios": {
"version": "2.1.0"
"version": "2.1.1"
}
}
}
31 changes: 13 additions & 18 deletions tests/app/tests/snippets.ts
Original file line number Diff line number Diff line change
@@ -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";
Expand All @@ -24,7 +23,7 @@ describe('Snippets', () => {
before(() => {
return TestApp.create().then((app) => {
testApp = app;
})
});
});

after(() => {
Expand Down Expand Up @@ -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;
Expand All @@ -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) {
Expand All @@ -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) {
Expand All @@ -117,7 +112,7 @@ describe('Snippets Navigation', () => {
cleanup();
done();
}
})
})
});
});
});
});