refactor(router): rename candidate into snapshot
This commit is contained in:
parent
c5cca8e098
commit
243612e36d
|
@ -1,18 +1,18 @@
|
|||
import { RouterStateCandidate, ActivatedRouteCandidate, RouterState, ActivatedRoute } from './router_state';
|
||||
import { RouterStateSnapshot, ActivatedRouteSnapshot, RouterState, ActivatedRoute } from './router_state';
|
||||
import { TreeNode } from './utils/tree';
|
||||
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
||||
|
||||
export function createRouterState(curr: RouterStateCandidate, prevState: RouterState): RouterState {
|
||||
export function createRouterState(curr: RouterStateSnapshot, prevState: RouterState): RouterState {
|
||||
const root = createNode(curr._root, prevState ? prevState._root : null);
|
||||
const queryParams = prevState ? prevState.queryParams : new BehaviorSubject(curr.queryParams);
|
||||
const fragment = prevState ? prevState.fragment : new BehaviorSubject(curr.fragment);
|
||||
return new RouterState(root, queryParams, fragment, curr);
|
||||
}
|
||||
|
||||
function createNode(curr:TreeNode<ActivatedRouteCandidate>, prevState?:TreeNode<ActivatedRoute>):TreeNode<ActivatedRoute> {
|
||||
if (prevState && equalRouteCandidates(prevState.value.candidate, curr.value)) {
|
||||
function createNode(curr:TreeNode<ActivatedRouteSnapshot>, prevState?:TreeNode<ActivatedRoute>):TreeNode<ActivatedRoute> {
|
||||
if (prevState && equalRouteSnapshots(prevState.value.snapshot, curr.value)) {
|
||||
const value = prevState.value;
|
||||
value.candidate = curr.value;
|
||||
value.snapshot = curr.value;
|
||||
|
||||
const children = createOrReuseChildren(curr, prevState);
|
||||
return new TreeNode<ActivatedRoute>(value, children);
|
||||
|
@ -24,9 +24,9 @@ function createNode(curr:TreeNode<ActivatedRouteCandidate>, prevState?:TreeNode<
|
|||
}
|
||||
}
|
||||
|
||||
function createOrReuseChildren(curr:TreeNode<ActivatedRouteCandidate>, prevState:TreeNode<ActivatedRoute>) {
|
||||
function createOrReuseChildren(curr:TreeNode<ActivatedRouteSnapshot>, prevState:TreeNode<ActivatedRoute>) {
|
||||
return curr.children.map(child => {
|
||||
const index = prevState.children.findIndex(p => equalRouteCandidates(p.value.candidate, child.value));
|
||||
const index = prevState.children.findIndex(p => equalRouteSnapshots(p.value.snapshot, child.value));
|
||||
if (index >= 0) {
|
||||
return createNode(child, prevState.children[index]);
|
||||
} else {
|
||||
|
@ -35,10 +35,10 @@ function createOrReuseChildren(curr:TreeNode<ActivatedRouteCandidate>, prevState
|
|||
});
|
||||
}
|
||||
|
||||
function createActivatedRoute(c:ActivatedRouteCandidate) {
|
||||
function createActivatedRoute(c:ActivatedRouteSnapshot) {
|
||||
return new ActivatedRoute(new BehaviorSubject(c.urlSegments), new BehaviorSubject(c.params), c.outlet, c.component, c);
|
||||
}
|
||||
|
||||
function equalRouteCandidates(a: ActivatedRouteCandidate, b: ActivatedRouteCandidate): boolean {
|
||||
function equalRouteSnapshots(a: ActivatedRouteSnapshot, b: ActivatedRouteSnapshot): boolean {
|
||||
return a._routeConfig === b._routeConfig;
|
||||
}
|
|
@ -1,28 +1,28 @@
|
|||
import { UrlTree, UrlSegment } from './url_tree';
|
||||
import { flatten, first, merge } from './utils/collection';
|
||||
import { TreeNode } from './utils/tree';
|
||||
import { RouterStateCandidate, ActivatedRouteCandidate } from './router_state';
|
||||
import { RouterStateSnapshot, ActivatedRouteSnapshot } from './router_state';
|
||||
import { Params, PRIMARY_OUTLET } from './shared';
|
||||
import { RouterConfig, Route } from './config';
|
||||
import { Type } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export function recognize(rootComponentType: Type, config: RouterConfig, url: UrlTree): Observable<RouterStateCandidate> {
|
||||
export function recognize(rootComponentType: Type, config: RouterConfig, url: UrlTree): Observable<RouterStateSnapshot> {
|
||||
try {
|
||||
const match = new MatchResult(rootComponentType, config, [url.root], {}, url._root.children, [], PRIMARY_OUTLET, null);
|
||||
const roots = constructActivatedRoute(match);
|
||||
const res = new RouterStateCandidate(roots[0], url.queryParameters, url.fragment);
|
||||
return new Observable<RouterStateCandidate>(obs => {
|
||||
const res = new RouterStateSnapshot(roots[0], url.queryParameters, url.fragment);
|
||||
return new Observable<RouterStateSnapshot>(obs => {
|
||||
obs.next(res);
|
||||
obs.complete();
|
||||
});
|
||||
} catch(e) {
|
||||
return new Observable<RouterStateCandidate>(obs => obs.error(e));
|
||||
return new Observable<RouterStateSnapshot>(obs => obs.error(e));
|
||||
}
|
||||
}
|
||||
|
||||
function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteCandidate>[] {
|
||||
const activatedRoute = createActivatedRouteCandidate(match);
|
||||
function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
const activatedRoute = createActivatedRouteSnapshot(match);
|
||||
if (match.leftOverUrl.length > 0) {
|
||||
const children = recognizeMany(match.children, match.leftOverUrl);
|
||||
checkOutletNameUniqueness(children);
|
||||
|
@ -31,21 +31,21 @@ function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteCan
|
|||
if (b.value.outlet === PRIMARY_OUTLET) return 1;
|
||||
return a.value.outlet.localeCompare(b.value.outlet)
|
||||
});
|
||||
return [new TreeNode<ActivatedRouteCandidate>(activatedRoute, children)];
|
||||
return [new TreeNode<ActivatedRouteSnapshot>(activatedRoute, children)];
|
||||
} else {
|
||||
return [new TreeNode<ActivatedRouteCandidate>(activatedRoute, [])];
|
||||
return [new TreeNode<ActivatedRouteSnapshot>(activatedRoute, [])];
|
||||
}
|
||||
}
|
||||
|
||||
function recognizeMany(config: Route[], urls: TreeNode<UrlSegment>[]): TreeNode<ActivatedRouteCandidate>[] {
|
||||
function recognizeMany(config: Route[], urls: TreeNode<UrlSegment>[]): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
return flatten(urls.map(url => recognizeOne(config, url)));
|
||||
}
|
||||
|
||||
function createActivatedRouteCandidate(match: MatchResult): ActivatedRouteCandidate {
|
||||
return new ActivatedRouteCandidate(match.consumedUrlSegments, match.parameters, match.outlet, match.component, match.route);
|
||||
function createActivatedRouteSnapshot(match: MatchResult): ActivatedRouteSnapshot {
|
||||
return new ActivatedRouteSnapshot(match.consumedUrlSegments, match.parameters, match.outlet, match.component, match.route);
|
||||
}
|
||||
|
||||
function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<ActivatedRouteCandidate>[] {
|
||||
function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
const m = match(config, url);
|
||||
const primary = constructActivatedRoute(m);
|
||||
const secondary = recognizeMany(config, m.secondary);
|
||||
|
@ -54,7 +54,7 @@ function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<Acti
|
|||
return res;
|
||||
}
|
||||
|
||||
function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteCandidate>[]): TreeNode<ActivatedRouteCandidate>[] {
|
||||
function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
let names = {};
|
||||
nodes.forEach(n => {
|
||||
let routeWithSameOutletName = names[n.value.outlet];
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import { RouterStateCandidate, ActivatedRouteCandidate } from './router_state';
|
||||
import { RouterStateSnapshot, ActivatedRouteSnapshot } from './router_state';
|
||||
import { TreeNode } from './utils/tree';
|
||||
import { ComponentResolver } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
@ -7,11 +7,11 @@ import {forkJoin} from 'rxjs/observable/forkJoin';
|
|||
import {fromPromise} from 'rxjs/observable/fromPromise';
|
||||
import 'rxjs/add/operator/toPromise';
|
||||
|
||||
export function resolve(resolver: ComponentResolver, state: RouterStateCandidate): Observable<RouterStateCandidate> {
|
||||
export function resolve(resolver: ComponentResolver, state: RouterStateSnapshot): Observable<RouterStateSnapshot> {
|
||||
return resolveNode(resolver, state._root).map(_ => state);
|
||||
}
|
||||
|
||||
function resolveNode(resolver: ComponentResolver, node: TreeNode<ActivatedRouteCandidate>): Observable<any> {
|
||||
function resolveNode(resolver: ComponentResolver, node: TreeNode<ActivatedRouteSnapshot>): Observable<any> {
|
||||
if (node.children.length === 0) {
|
||||
return fromPromise(resolver.resolveComponent(<any>node.value.component).then(factory => {
|
||||
node.value._resolvedComponentFactory = factory;
|
||||
|
|
|
@ -8,7 +8,7 @@ import { createRouterState } from './create_router_state';
|
|||
import { TreeNode } from './utils/tree';
|
||||
import { UrlTree, createEmptyUrlTree } from './url_tree';
|
||||
import { PRIMARY_OUTLET, Params } from './shared';
|
||||
import { createEmptyState, RouterState, RouterStateCandidate, ActivatedRoute, ActivatedRouteCandidate} from './router_state';
|
||||
import { createEmptyState, RouterState, RouterStateSnapshot, ActivatedRoute, ActivatedRouteSnapshot} from './router_state';
|
||||
import { RouterConfig } from './config';
|
||||
import { RouterOutlet } from './directives/router_outlet';
|
||||
import { createUrlTree } from './create_url_tree';
|
||||
|
@ -162,17 +162,17 @@ export class Router {
|
|||
|
||||
private runNavigate(url:UrlTree, pop?:boolean):Observable<any> {
|
||||
let state;
|
||||
const r = recognize(this.rootComponentType, this.config, url).mergeMap((newRouterStateCandidate) => {
|
||||
return resolve(this.resolver, newRouterStateCandidate);
|
||||
const r = recognize(this.rootComponentType, this.config, url).mergeMap((newRouterStateSnapshot) => {
|
||||
return resolve(this.resolver, newRouterStateSnapshot);
|
||||
|
||||
}).map((routerStateCandidate) => {
|
||||
return createRouterState(routerStateCandidate, this.currentRouterState);
|
||||
}).map((routerStateSnapshot) => {
|
||||
return createRouterState(routerStateSnapshot, this.currentRouterState);
|
||||
|
||||
}).map((newState:RouterState) => {
|
||||
state = newState;
|
||||
|
||||
}).mergeMap(_ => {
|
||||
return new GuardChecks(state.candidate, this.currentRouterState.candidate, this.injector).check(this.outletMap);
|
||||
return new GuardChecks(state.snapshot, this.currentRouterState.snapshot, this.injector).check(this.outletMap);
|
||||
});
|
||||
|
||||
r.subscribe((shouldActivate) => {
|
||||
|
@ -192,7 +192,7 @@ export class Router {
|
|||
|
||||
class GuardChecks {
|
||||
private checks = [];
|
||||
constructor(private future: RouterStateCandidate, private curr: RouterStateCandidate, private injector: Injector) {}
|
||||
constructor(private future: RouterStateSnapshot, private curr: RouterStateSnapshot, private injector: Injector) {}
|
||||
|
||||
check(parentOutletMap: RouterOutletMap): Observable<boolean> {
|
||||
const futureRoot = this.future._root;
|
||||
|
@ -202,8 +202,8 @@ class GuardChecks {
|
|||
return forkJoin(this.checks.map(s => this.runCanActivate(s))).map(and);
|
||||
}
|
||||
|
||||
private traverseChildRoutes(futureNode: TreeNode<ActivatedRouteCandidate>,
|
||||
currNode: TreeNode<ActivatedRouteCandidate> | null,
|
||||
private traverseChildRoutes(futureNode: TreeNode<ActivatedRouteSnapshot>,
|
||||
currNode: TreeNode<ActivatedRouteSnapshot> | null,
|
||||
outletMap: RouterOutletMap): void {
|
||||
const prevChildren = nodeChildrenAsMap(currNode);
|
||||
futureNode.children.forEach(c => {
|
||||
|
@ -213,7 +213,7 @@ class GuardChecks {
|
|||
forEach(prevChildren, (v, k) => this.deactivateOutletAndItChildren(outletMap._outlets[k]));
|
||||
}
|
||||
|
||||
traverseRoutes(futureNode: TreeNode<ActivatedRouteCandidate>, currNode: TreeNode<ActivatedRouteCandidate> | null,
|
||||
traverseRoutes(futureNode: TreeNode<ActivatedRouteSnapshot>, currNode: TreeNode<ActivatedRouteSnapshot> | null,
|
||||
parentOutletMap: RouterOutletMap): void {
|
||||
const future = futureNode.value;
|
||||
const curr = currNode ? currNode.value : null;
|
||||
|
@ -232,7 +232,7 @@ class GuardChecks {
|
|||
|
||||
private deactivateOutletAndItChildren(outlet: RouterOutlet): void {}
|
||||
|
||||
private runCanActivate(future: ActivatedRouteCandidate): Observable<boolean> {
|
||||
private runCanActivate(future: ActivatedRouteSnapshot): Observable<boolean> {
|
||||
const canActivate = future._routeConfig ? future._routeConfig.canActivate : null;
|
||||
if (!canActivate || canActivate.length === 0) return of(true);
|
||||
return forkJoin(canActivate.map(c => {
|
||||
|
@ -286,7 +286,7 @@ class ActivateRoutes {
|
|||
{provide: ActivatedRoute, useValue: future},
|
||||
{provide: RouterOutletMap, useValue: outletMap}
|
||||
]);
|
||||
outlet.activate(future.candidate._resolvedComponentFactory, resolved, outletMap);
|
||||
outlet.activate(future.snapshot._resolvedComponentFactory, resolved, outletMap);
|
||||
pushValues(future);
|
||||
}
|
||||
|
||||
|
@ -299,19 +299,19 @@ class ActivateRoutes {
|
|||
}
|
||||
|
||||
function pushValues(route: ActivatedRoute): void {
|
||||
if (!shallowEqual(route.candidate.params, (<any>route.params).value)) {
|
||||
(<any>route.urlSegments).next(route.candidate.urlSegments);
|
||||
(<any>route.params).next(route.candidate.params);
|
||||
if (!shallowEqual(route.snapshot.params, (<any>route.params).value)) {
|
||||
(<any>route.urlSegments).next(route.snapshot.urlSegments);
|
||||
(<any>route.params).next(route.snapshot.params);
|
||||
}
|
||||
}
|
||||
|
||||
function pushQueryParamsAndFragment(state: RouterState): void {
|
||||
if (!shallowEqual(state.candidate.queryParams, (<any>state.queryParams).value)) {
|
||||
(<any>state.queryParams).next(state.candidate.queryParams);
|
||||
if (!shallowEqual(state.snapshot.queryParams, (<any>state.queryParams).value)) {
|
||||
(<any>state.queryParams).next(state.snapshot.queryParams);
|
||||
}
|
||||
|
||||
if (state.candidate.fragment !== (<any>state.fragment).value) {
|
||||
(<any>state.fragment).next(state.candidate.fragment);
|
||||
if (state.snapshot.fragment !== (<any>state.fragment).value) {
|
||||
(<any>state.fragment).next(state.snapshot.fragment);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ import { BehaviorSubject } from 'rxjs/BehaviorSubject';
|
|||
import { Type, ComponentFactory } from '@angular/core';
|
||||
|
||||
/**
|
||||
* The state of the router at a particular moment in time.
|
||||
* The state of the router.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
|
@ -22,32 +22,33 @@ import { Type, ComponentFactory } from '@angular/core';
|
|||
* ```
|
||||
*/
|
||||
export class RouterState extends Tree<ActivatedRoute> {
|
||||
constructor(root: TreeNode<ActivatedRoute>, public queryParams: Observable<Params>, public fragment: Observable<string>, public candidate: RouterStateCandidate) {
|
||||
constructor(root: TreeNode<ActivatedRoute>, public queryParams: Observable<Params>, public fragment: Observable<string>, public snapshot: RouterStateSnapshot) {
|
||||
super(root);
|
||||
}
|
||||
}
|
||||
|
||||
export function createEmptyState(rootComponent: Type): RouterState {
|
||||
const candidate = createEmptyStateCandidate(rootComponent);
|
||||
const snapshot = createEmptyStateSnapshot(rootComponent);
|
||||
const emptyUrl = new BehaviorSubject([new UrlSegment("", {}, PRIMARY_OUTLET)]);
|
||||
const emptyParams = new BehaviorSubject({});
|
||||
const emptyQueryParams = new BehaviorSubject({});
|
||||
const fragment = new BehaviorSubject("");
|
||||
const activated = new ActivatedRoute(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, candidate.root);
|
||||
return new RouterState(new TreeNode<ActivatedRoute>(activated, []), emptyQueryParams, fragment, candidate);
|
||||
const activated = new ActivatedRoute(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, snapshot.root);
|
||||
return new RouterState(new TreeNode<ActivatedRoute>(activated, []), emptyQueryParams, fragment, snapshot);
|
||||
}
|
||||
|
||||
function createEmptyStateCandidate(rootComponent: Type): RouterStateCandidate {
|
||||
function createEmptyStateSnapshot(rootComponent: Type): RouterStateSnapshot {
|
||||
const emptyUrl = [new UrlSegment("", {}, PRIMARY_OUTLET)];
|
||||
const emptyParams = {};
|
||||
const emptyQueryParams = {};
|
||||
const fragment = "";
|
||||
const activated = new ActivatedRouteCandidate(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, null);
|
||||
return new RouterStateCandidate(new TreeNode<ActivatedRouteCandidate>(activated, []), emptyQueryParams, fragment);
|
||||
const activated = new ActivatedRouteSnapshot(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, null);
|
||||
return new RouterStateSnapshot(new TreeNode<ActivatedRouteSnapshot>(activated, []), emptyQueryParams, fragment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the information about a component loaded in an outlet.
|
||||
* Contains the information about a component loaded in an outlet. The information is provided through
|
||||
* the params and urlSegments observables.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
|
@ -64,11 +65,24 @@ export class ActivatedRoute {
|
|||
public params: Observable<Params>,
|
||||
public outlet: string,
|
||||
public component: Type | string,
|
||||
public candidate: ActivatedRouteCandidate
|
||||
public snapshot: ActivatedRouteSnapshot
|
||||
) {}
|
||||
}
|
||||
|
||||
export class ActivatedRouteCandidate {
|
||||
/**
|
||||
* Contains the information about a component loaded in an outlet at a particular moment in time.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* ```
|
||||
* class MyComponent {
|
||||
* constructor(route: ActivatedRoute) {
|
||||
* const id: string = route.snapshot.params.id;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export class ActivatedRouteSnapshot {
|
||||
/**
|
||||
* @internal
|
||||
*/
|
||||
|
@ -86,8 +100,21 @@ export class ActivatedRouteCandidate {
|
|||
}
|
||||
}
|
||||
|
||||
export class RouterStateCandidate extends Tree<ActivatedRouteCandidate> {
|
||||
constructor(root: TreeNode<ActivatedRouteCandidate>, public queryParams: Params, public fragment: string) {
|
||||
/**
|
||||
* The state of the router at a particular moment in time.
|
||||
*
|
||||
* ### Usage
|
||||
*
|
||||
* ```
|
||||
* class MyComponent {
|
||||
* constructor(router: Router) {
|
||||
* const snapshot = router.routerState.snapshot;
|
||||
* }
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export class RouterStateSnapshot extends Tree<ActivatedRouteSnapshot> {
|
||||
constructor(root: TreeNode<ActivatedRouteSnapshot>, public queryParams: Params, public fragment: string) {
|
||||
super(root);
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import {DefaultUrlSerializer} from '../src/url_serializer';
|
||||
import {UrlTree} from '../src/url_tree';
|
||||
import {Params, PRIMARY_OUTLET} from '../src/shared';
|
||||
import {ActivatedRoute, ActivatedRouteCandidate, RouterStateCandidate, createEmptyState} from '../src/router_state';
|
||||
import {ActivatedRoute, ActivatedRouteSnapshot, RouterStateSnapshot, createEmptyState} from '../src/router_state';
|
||||
import {createRouterState} from '../src/create_router_state';
|
||||
import {recognize} from '../src/recognize';
|
||||
import {RouterConfig} from '../src/config';
|
||||
|
@ -44,7 +44,7 @@ describe('create router state', () => {
|
|||
});
|
||||
});
|
||||
|
||||
function createState(config: RouterConfig, url: string): RouterStateCandidate {
|
||||
function createState(config: RouterConfig, url: string): RouterStateSnapshot {
|
||||
let res;
|
||||
recognize(RootComponent, config, tree(url)).forEach(s => res = s);
|
||||
return res;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import {DefaultUrlSerializer} from '../src/url_serializer';
|
||||
import {UrlTree} from '../src/url_tree';
|
||||
import {Params, PRIMARY_OUTLET} from '../src/shared';
|
||||
import {ActivatedRouteCandidate} from '../src/router_state';
|
||||
import {ActivatedRouteSnapshot} from '../src/router_state';
|
||||
import {recognize} from '../src/recognize';
|
||||
|
||||
describe('recognize', () => {
|
||||
|
@ -196,7 +196,7 @@ describe('recognize', () => {
|
|||
});
|
||||
});
|
||||
|
||||
function checkActivatedRoute(actual: ActivatedRouteCandidate | null, url: string, params: Params, cmp: Function, outlet: string = PRIMARY_OUTLET):void {
|
||||
function checkActivatedRoute(actual: ActivatedRouteSnapshot | null, url: string, params: Params, cmp: Function, outlet: string = PRIMARY_OUTLET):void {
|
||||
if (actual === null) {
|
||||
expect(actual).toBeDefined();
|
||||
} else {
|
||||
|
|
Loading…
Reference in New Issue