Skip to content

Commit 071f471

Browse files
author
Alexander Vakrilov
authored
Merge pull request #355 from NativeScript/page-outlet-v3
PageRoute
2 parents 87bc045 + 520fe02 commit 071f471

File tree

10 files changed

+81
-47
lines changed

10 files changed

+81
-47
lines changed

Diff for: .gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ nativescript-angular/**/*.js
1616
.nvm
1717
.vscode
1818
.DS_Store
19+
npm-debug.log
1920
nativescript-angular*.tgz
2021

2122
tests/app/**/*.js

Diff for: nativescript-angular/router/ns-router-link.ts

+15-9
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
import {Directive, HostBinding, HostListener, Input} from '@angular/core';
2-
import {LocationStrategy} from '@angular/common';
3-
import {Router, ActivatedRoute, UrlTree} from '@angular/router';
1+
import {Directive, HostListener, Input, Optional} from '@angular/core';
2+
import {Router, ActivatedRoute} from '@angular/router';
43
import {routerLog} from "../trace";
4+
import {PageRoute} from "./page-router-outlet";
55

66
/**
7-
* The RouterLink directive lets you link to specific parts of your app.
7+
* The nsRouterLink directive lets you link to specific parts of your app.
88
*
99
* Consider the following route configuration:
1010
@@ -35,10 +35,14 @@ export class NSRouterLink {
3535
@Input() queryParams: { [k: string]: any };
3636
@Input() fragment: string;
3737

38-
/**
39-
* @internal
40-
*/
41-
constructor(private router: Router, private route: ActivatedRoute) { }
38+
private usePageRoute: boolean;
39+
40+
constructor(
41+
private router: Router,
42+
private route: ActivatedRoute,
43+
@Optional() private pageRoute: PageRoute) {
44+
this.usePageRoute = (this.pageRoute && this.route === this.pageRoute.activatedRoute.getValue());
45+
}
4246

4347
@Input("nsRouterLink")
4448
set params(data: any[] | string) {
@@ -52,8 +56,10 @@ export class NSRouterLink {
5256
@HostListener("tap")
5357
onTap() {
5458
routerLog("nsRouterLink.tapped: " + this.commands);
59+
const currentRoute = this.usePageRoute ? this.pageRoute.activatedRoute.getValue() : this.route;
60+
5561
this.router.navigate(
5662
this.commands,
57-
{ relativeTo: this.route, queryParams: this.queryParams, fragment: this.fragment });
63+
{ relativeTo: currentRoute, queryParams: this.queryParams, fragment: this.fragment });
5864
}
5965
}

Diff for: nativescript-angular/router/ns-router.ts

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import {NSLocationStrategy} from './ns-location-strategy';
1010
import {NativescriptPlatformLocation} from './ns-platform-location';
1111

1212
export {routerTraceCategory} from "../trace";
13+
export {PageRoute} from './page-router-outlet';
1314

1415
export const NS_ROUTER_PROVIDERS: any[] = [
1516
NSLocationStrategy,

Diff for: nativescript-angular/router/page-router-outlet.ts

+39-10
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,9 @@ import {
44
Inject, ComponentResolver, provide, ComponentFactoryResolver,
55
NoComponentFactoryError} from '@angular/core';
66

7-
import {isBlank, isPresent} from '@angular/core/src/facade/lang';
7+
import {isPresent} from '@angular/core/src/facade/lang';
88

9-
import {RouterOutletMap, ActivatedRoute, RouterOutlet, PRIMARY_OUTLET} from '@angular/router';
9+
import {RouterOutletMap, ActivatedRoute, PRIMARY_OUTLET} from '@angular/router';
1010
import {NSLocationStrategy} from "./ns-location-strategy";
1111
import {DEVICE} from "../platform-providers";
1212
import {Device} from "platform";
@@ -15,20 +15,35 @@ import {DetachedLoader} from "../common/detached-loader";
1515
import {ViewUtil} from "../view-util";
1616
import {topmost} from "ui/frame";
1717
import {Page, NavigatedData} from "ui/page";
18+
import {BehaviorSubject} from "rxjs";
1819

1920
interface CacheItem {
2021
componentRef: ComponentRef<any>;
22+
reusedRoute: PageRoute;
23+
outletMap: RouterOutletMap;
2124
loaderRef?: ComponentRef<any>;
2225
}
2326

27+
export class PageRoute {
28+
activatedRoute: BehaviorSubject<ActivatedRoute>;
29+
constructor(startRoute: ActivatedRoute) {
30+
this.activatedRoute = new BehaviorSubject(startRoute);
31+
}
32+
}
33+
34+
2435
/**
2536
* Reference Cache
2637
*/
2738
class RefCache {
2839
private cache: Array<CacheItem> = new Array<CacheItem>();
2940

30-
public push(comp: ComponentRef<any>, loaderRef?: ComponentRef<any>) {
31-
this.cache.push({ componentRef: comp, loaderRef: loaderRef });
41+
public push(
42+
componentRef: ComponentRef<any>,
43+
reusedRoute: PageRoute,
44+
outletMap: RouterOutletMap,
45+
loaderRef: ComponentRef<any>) {
46+
this.cache.push({ componentRef, reusedRoute, outletMap, loaderRef });
3247
}
3348

3449
public pop(): CacheItem {
@@ -125,23 +140,27 @@ export class PageRouterOutlet {
125140
this.currentActivatedRoute = activatedRoute;
126141

127142
if (this.locationStrategy.isPageNavigatingBack()) {
128-
this.activateOnGoBack(activatedRoute, providers);
143+
this.activateOnGoBack(activatedRoute, providers, outletMap);
129144
} else {
130-
this.activateOnGoForward(activatedRoute, providers);
145+
this.activateOnGoForward(activatedRoute, providers, outletMap);
131146
}
132147
}
133148

134149
private activateOnGoForward(
135150
activatedRoute: ActivatedRoute,
136-
providers: ResolvedReflectiveProvider[]): void {
151+
providers: ResolvedReflectiveProvider[],
152+
outletMap: RouterOutletMap): void {
137153
const factory = this.getComponentFactory(activatedRoute);
138154

155+
const reusedRoute = new PageRoute(activatedRoute);
156+
providers = [...providers, ...ReflectiveInjector.resolve([{ provide: PageRoute, useValue: reusedRoute }])];
157+
139158
if (this.isInitalPage) {
140159
log("PageRouterOutlet.activate() inital page - just load component: " + activatedRoute.component);
141160
this.isInitalPage = false;
142161
const inj = ReflectiveInjector.fromResolvedProviders(providers, this.containerRef.parentInjector);
143162
this.currnetActivatedComp = this.containerRef.createComponent(factory, this.containerRef.length, inj, []);
144-
this.refCache.push(this.currnetActivatedComp, null);
163+
this.refCache.push(this.currnetActivatedComp, reusedRoute, outletMap, null);
145164

146165
} else {
147166
log("PageRouterOutlet.activate() forward navigation - create detached loader in the loader container: " + activatedRoute.component);
@@ -153,18 +172,28 @@ export class PageRouterOutlet {
153172

154173
this.currnetActivatedComp = loaderRef.instance.loadWithFactory(factory);
155174
this.loadComponentInPage(page, this.currnetActivatedComp);
156-
this.refCache.push(this.currnetActivatedComp, loaderRef);
175+
this.refCache.push(this.currnetActivatedComp, reusedRoute, outletMap, loaderRef);
157176
}
158177
}
159178

160179
private activateOnGoBack(
161180
activatedRoute: ActivatedRoute,
162-
providers: ResolvedReflectiveProvider[]): void {
181+
providers: ResolvedReflectiveProvider[],
182+
outletMap: RouterOutletMap): void {
163183
log("PageRouterOutlet.activate() - Back naviation, so load from cache: " + activatedRoute.component);
164184

165185
this.locationStrategy.finishBackPageNavigation();
166186

167187
let cacheItem = this.refCache.peek();
188+
cacheItem.reusedRoute.activatedRoute.next(activatedRoute);
189+
190+
this.outletMap = cacheItem.outletMap;
191+
192+
// HACK: Fill the outlet map provided by the router, with the outlets that we have cached.
193+
// This is needed beacuse the component is taken form the cache and not created - so it will not register
194+
// its child router-outlets to the newly created outlet map.
195+
Object.assign(outletMap, cacheItem.outletMap);
196+
168197
this.currnetActivatedComp = cacheItem.componentRef;
169198
}
170199

Diff for: ng-sample/.vscode/launch.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@
6767
"platform": "android",
6868
"request": "attach",
6969
"appRoot": "${workspaceRoot}",
70-
"sourceMaps": false,
70+
"sourceMaps": true,
7171
"diagnosticLogging": false,
7272
"emulator": false
7373
},
@@ -77,7 +77,7 @@
7777
"platform": "android",
7878
"request": "attach",
7979
"appRoot": "${workspaceRoot}",
80-
"sourceMaps": false,
80+
"sourceMaps": true,
8181
"diagnosticLogging": false,
8282
"emulator": true
8383
}

Diff for: ng-sample/app/app.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import { rendererTraceCategory, routerTraceCategory, listViewTraceCategory } fro
1515

1616
import trace = require("trace");
1717
// trace.setCategories(rendererTraceCategory);
18-
// trace.setCategories(routerTraceCategory);
18+
trace.setCategories(routerTraceCategory);
1919
// trace.setCategories(listViewTraceCategory);
2020
trace.enable();
2121

@@ -53,7 +53,7 @@ import { AnimationStatesTest } from "./examples/animation/animation-states-test"
5353
// nativeScriptBootstrap(ListTest);
5454
// nativeScriptBootstrap(ListTestAsync);
5555
//nativeScriptBootstrap(ImageTest);
56-
nativeScriptBootstrap(HttpTest);
56+
// nativeScriptBootstrap(HttpTest);
5757
//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED], { startPageActionBarHidden: false });
5858
//nativeScriptBootstrap(ActionBarTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);
5959
//nativeScriptBootstrap(ModalTest);
@@ -62,7 +62,7 @@ nativeScriptBootstrap(HttpTest);
6262
// new router
6363
// nativeScriptBootstrap(RouterOutletAppComponent, [RouterOutletRouterProviders]);
6464
// nativeScriptBootstrap(PageRouterOutletAppComponent, [PageRouterOutletRouterProviders]);
65-
// nativeScriptBootstrap(PageRouterOutletNestedAppComponent, [PageRouterOutletNestedRouterProviders]);
65+
nativeScriptBootstrap(PageRouterOutletNestedAppComponent, [PageRouterOutletNestedRouterProviders]);
6666

6767
// router-deprecated
6868
// nativeScriptBootstrap(NavigationTest, [NS_ROUTER_PROVIDERS_DEPRECATED]);

Diff for: ng-sample/app/examples/router/page-router-outlet-nested-test.ts

+2
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,8 @@ class DetailComponent {
8585
<StackLayout>
8686
<Label [text]="'Second component: ' + (depth$ | async)" class="title"></Label>
8787
88+
<Button class="link" text="Nav to First" [nsRouterLink]="['/']"></Button>
89+
8890
<StackLayout class="nav">
8991
<Button class="link" text="< BACK" (tap)="goBack()"></Button>
9092
<Button class="link" [text]="'Second ' + (nextDepth$ | async) + ' >'" [nsRouterLink]="['/second', (nextDepth$ | async)]"></Button>

Diff for: ng-sample/app/examples/router/page-router-outlet-test.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import { Component, OnInit, OnDestroy } from "@angular/core";
2-
import { RouterConfig, ActivatedRoute, Router, ROUTER_DIRECTIVES, Event } from '@angular/router';
2+
import { RouterConfig, ActivatedRoute, Router, ROUTER_DIRECTIVES } from '@angular/router';
33
import { Observable } from "rxjs";
4-
import { NS_ROUTER_DIRECTIVES, nsProvideRouter} from "nativescript-angular/router"
5-
import { Location, LocationStrategy} from '@angular/common';
4+
import { NS_ROUTER_DIRECTIVES, nsProvideRouter} from "nativescript-angular/router";
5+
import { Location } from '@angular/common';
66
import { Page } from "ui/page";
77

88

@@ -113,7 +113,7 @@ export class PageRouterOutletAppComponent {
113113
constructor(router: Router, private location: Location) {
114114
router.events.subscribe((e) => {
115115
console.log("--EVENT-->: " + e.toString());
116-
})
116+
});
117117
}
118118
}
119119

Diff for: ng-sample/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
"version": "2.1.1"
6161
},
6262
"tns-ios": {
63-
"version": "2.1.0"
63+
"version": "2.1.1"
6464
}
6565
}
6666
}

Diff for: tests/app/tests/snippets.ts

+13-18
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
//make sure you import mocha-config before @angular/core
22
import {assert} from "./test-config";
33

4-
import {Component, ElementRef, Renderer} from "@angular/core";
5-
import {NavigationEnd, NavigationStart, NavigationError} from "@angular/router";
4+
import {NavigationEnd, NavigationStart} from "@angular/router";
65

76
import {Subscription} from "rxjs";
87
import {TestApp, bootstrapTestApp, destroyTestApp} from "./test-app";
@@ -24,7 +23,7 @@ describe('Snippets', () => {
2423
before(() => {
2524
return TestApp.create().then((app) => {
2625
testApp = app;
27-
})
26+
});
2827
});
2928

3029
after(() => {
@@ -54,13 +53,13 @@ describe('Snippets', () => {
5453
setTimeout(done, 10);
5554
});
5655
});
57-
})
56+
});
5857

5958
describe('Snippets Navigation', () => {
60-
var runningApp: any;
61-
var subscription: Subscription;
59+
let runningApp: any;
60+
let subscription: Subscription;
6261

63-
var cleanup = () => {
62+
const cleanup = () => {
6463
if (subscription) {
6564
subscription.unsubscribe();
6665
subscription = null;
@@ -69,15 +68,14 @@ describe('Snippets Navigation', () => {
6968
destroyTestApp(runningApp);
7069
runningApp = null;
7170
}
72-
}
71+
};
7372

7473
after(cleanup);
7574

7675
it("router-outlet app", (done) => {
7776
bootstrapTestApp(NavigationApp, [APP_ROUTER_PROVIDERS]).then((app) => {
78-
console.log("app bootstraped");
7977
runningApp = app;
80-
var navStarted = false;
78+
let navStarted = false;
8179

8280
subscription = app.router.events.subscribe((e) => {
8381
if (e instanceof NavigationStart) {
@@ -92,17 +90,14 @@ describe('Snippets Navigation', () => {
9290
cleanup();
9391
done();
9492
}
95-
})
96-
})
93+
});
94+
});
9795
});
9896

9997
it("page-router-outlet app", (done) => {
100-
console.log("------------- PageNavigationApp: " + PageNavigationApp);
101-
10298
bootstrapTestApp(PageNavigationApp, [APP_ROUTER_PROVIDERS]).then((app) => {
103-
console.log("app bootstraped");
10499
runningApp = app;
105-
var navStarted = false;
100+
let navStarted = false;
106101

107102
subscription = app.router.events.subscribe((e) => {
108103
if (e instanceof NavigationStart) {
@@ -117,7 +112,7 @@ describe('Snippets Navigation', () => {
117112
cleanup();
118113
done();
119114
}
120-
})
121-
})
115+
});
116+
});
122117
});
123118
});

0 commit comments

Comments
 (0)