diff --git a/modules/@angular/router/src/create_router_state.ts b/modules/@angular/router/src/create_router_state.ts index 8b8f40f444..837c55f35d 100644 --- a/modules/@angular/router/src/create_router_state.ts +++ b/modules/@angular/router/src/create_router_state.ts @@ -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, prevState?:TreeNode):TreeNode { - if (prevState && equalRouteCandidates(prevState.value.candidate, curr.value)) { +function createNode(curr:TreeNode, prevState?:TreeNode):TreeNode { + 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(value, children); @@ -24,9 +24,9 @@ function createNode(curr:TreeNode, prevState?:TreeNode< } } -function createOrReuseChildren(curr:TreeNode, prevState:TreeNode) { +function createOrReuseChildren(curr:TreeNode, prevState:TreeNode) { 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, 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; } \ No newline at end of file diff --git a/modules/@angular/router/src/recognize.ts b/modules/@angular/router/src/recognize.ts index 5e7b8da6f6..d8c9196acb 100644 --- a/modules/@angular/router/src/recognize.ts +++ b/modules/@angular/router/src/recognize.ts @@ -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 { +export function recognize(rootComponentType: Type, config: RouterConfig, url: UrlTree): Observable { 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(obs => { + const res = new RouterStateSnapshot(roots[0], url.queryParameters, url.fragment); + return new Observable(obs => { obs.next(res); obs.complete(); }); } catch(e) { - return new Observable(obs => obs.error(e)); + return new Observable(obs => obs.error(e)); } } -function constructActivatedRoute(match: MatchResult): TreeNode[] { - const activatedRoute = createActivatedRouteCandidate(match); +function constructActivatedRoute(match: MatchResult): TreeNode[] { + 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(activatedRoute, children)]; + return [new TreeNode(activatedRoute, children)]; } else { - return [new TreeNode(activatedRoute, [])]; + return [new TreeNode(activatedRoute, [])]; } } -function recognizeMany(config: Route[], urls: TreeNode[]): TreeNode[] { +function recognizeMany(config: Route[], urls: TreeNode[]): TreeNode[] { 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): TreeNode[] { +function recognizeOne(config: Route[], url: TreeNode): TreeNode[] { 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): TreeNode[]): TreeNode[] { +function checkOutletNameUniqueness(nodes: TreeNode[]): TreeNode[] { let names = {}; nodes.forEach(n => { let routeWithSameOutletName = names[n.value.outlet]; diff --git a/modules/@angular/router/src/resolve.ts b/modules/@angular/router/src/resolve.ts index 737145a605..cdadbc5919 100644 --- a/modules/@angular/router/src/resolve.ts +++ b/modules/@angular/router/src/resolve.ts @@ -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 { +export function resolve(resolver: ComponentResolver, state: RouterStateSnapshot): Observable { return resolveNode(resolver, state._root).map(_ => state); } -function resolveNode(resolver: ComponentResolver, node: TreeNode): Observable { +function resolveNode(resolver: ComponentResolver, node: TreeNode): Observable { if (node.children.length === 0) { return fromPromise(resolver.resolveComponent(node.value.component).then(factory => { node.value._resolvedComponentFactory = factory; diff --git a/modules/@angular/router/src/router.ts b/modules/@angular/router/src/router.ts index cad1346bcc..3ba1335192 100644 --- a/modules/@angular/router/src/router.ts +++ b/modules/@angular/router/src/router.ts @@ -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 { 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 { 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, - currNode: TreeNode | null, + private traverseChildRoutes(futureNode: TreeNode, + currNode: TreeNode | 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, currNode: TreeNode | null, + traverseRoutes(futureNode: TreeNode, currNode: TreeNode | 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 { + private runCanActivate(future: ActivatedRouteSnapshot): Observable { 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, (route.params).value)) { - (route.urlSegments).next(route.candidate.urlSegments); - (route.params).next(route.candidate.params); + if (!shallowEqual(route.snapshot.params, (route.params).value)) { + (route.urlSegments).next(route.snapshot.urlSegments); + (route.params).next(route.snapshot.params); } } function pushQueryParamsAndFragment(state: RouterState): void { - if (!shallowEqual(state.candidate.queryParams, (state.queryParams).value)) { - (state.queryParams).next(state.candidate.queryParams); + if (!shallowEqual(state.snapshot.queryParams, (state.queryParams).value)) { + (state.queryParams).next(state.snapshot.queryParams); } - if (state.candidate.fragment !== (state.fragment).value) { - (state.fragment).next(state.candidate.fragment); + if (state.snapshot.fragment !== (state.fragment).value) { + (state.fragment).next(state.snapshot.fragment); } } diff --git a/modules/@angular/router/src/router_state.ts b/modules/@angular/router/src/router_state.ts index 702b3e5efb..c8355e4329 100644 --- a/modules/@angular/router/src/router_state.ts +++ b/modules/@angular/router/src/router_state.ts @@ -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 { - constructor(root: TreeNode, public queryParams: Observable, public fragment: Observable, public candidate: RouterStateCandidate) { + constructor(root: TreeNode, public queryParams: Observable, public fragment: Observable, 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(activated, []), emptyQueryParams, fragment, candidate); + const activated = new ActivatedRoute(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, snapshot.root); + return new RouterState(new TreeNode(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(activated, []), emptyQueryParams, fragment); + const activated = new ActivatedRouteSnapshot(emptyUrl, emptyParams, PRIMARY_OUTLET, rootComponent, null); + return new RouterStateSnapshot(new TreeNode(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, 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 { - constructor(root: TreeNode, 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 { + constructor(root: TreeNode, public queryParams: Params, public fragment: string) { super(root); } } \ No newline at end of file diff --git a/modules/@angular/router/test/create_router_state.spec.ts b/modules/@angular/router/test/create_router_state.spec.ts index 0ba2030598..d6b02d8ea8 100644 --- a/modules/@angular/router/test/create_router_state.spec.ts +++ b/modules/@angular/router/test/create_router_state.spec.ts @@ -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; diff --git a/modules/@angular/router/test/recognize.spec.ts b/modules/@angular/router/test/recognize.spec.ts index 82eda842ec..ed88ec4af1 100644 --- a/modules/@angular/router/test/recognize.spec.ts +++ b/modules/@angular/router/test/recognize.spec.ts @@ -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 {