parent
793ac3f6b4
commit
9b356d9b86
|
@ -7,6 +7,8 @@ import { RouterConfig, Route } from './config';
|
||||||
import { Type } from '@angular/core';
|
import { Type } from '@angular/core';
|
||||||
import { Observable } from 'rxjs/Observable';
|
import { Observable } from 'rxjs/Observable';
|
||||||
|
|
||||||
|
class CannotRecognize {}
|
||||||
|
|
||||||
export function recognize(rootComponentType: Type, config: RouterConfig, url: UrlTree): Observable<RouterStateSnapshot> {
|
export function recognize(rootComponentType: Type, config: RouterConfig, url: UrlTree): Observable<RouterStateSnapshot> {
|
||||||
try {
|
try {
|
||||||
const match = new MatchResult(rootComponentType, config, [url.root], {}, url._root.children, [], PRIMARY_OUTLET, null, url.root);
|
const match = new MatchResult(rootComponentType, config, [url.root], {}, url._root.children, [], PRIMARY_OUTLET, null, url.root);
|
||||||
|
@ -17,8 +19,12 @@ export function recognize(rootComponentType: Type, config: RouterConfig, url: Ur
|
||||||
obs.complete();
|
obs.complete();
|
||||||
});
|
});
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
|
if (e instanceof CannotRecognize) {
|
||||||
|
return new Observable<RouterStateSnapshot>(obs => obs.error(new Error("Cannot match any routes")));
|
||||||
|
} else {
|
||||||
return new Observable<RouterStateSnapshot>(obs => obs.error(e));
|
return new Observable<RouterStateSnapshot>(obs => obs.error(e));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteSnapshot>[] {
|
function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteSnapshot>[] {
|
||||||
|
@ -49,12 +55,21 @@ function createActivatedRouteSnapshot(match: MatchResult): ActivatedRouteSnapsho
|
||||||
}
|
}
|
||||||
|
|
||||||
function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<ActivatedRouteSnapshot>[] {
|
function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<ActivatedRouteSnapshot>[] {
|
||||||
const m = match(config, url);
|
const matches = match(config, url);
|
||||||
const primary = constructActivatedRoute(m);
|
for(let match of matches) {
|
||||||
const secondary = recognizeMany(config, m.secondary);
|
try {
|
||||||
|
const primary = constructActivatedRoute(match);
|
||||||
|
const secondary = recognizeMany(config, match.secondary);
|
||||||
const res = primary.concat(secondary);
|
const res = primary.concat(secondary);
|
||||||
checkOutletNameUniqueness(res);
|
checkOutletNameUniqueness(res);
|
||||||
return res;
|
return res;
|
||||||
|
} catch (e) {
|
||||||
|
if (! (e instanceof CannotRecognize)) {
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new CannotRecognize();
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): TreeNode<ActivatedRouteSnapshot>[] {
|
function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): TreeNode<ActivatedRouteSnapshot>[] {
|
||||||
|
@ -71,35 +86,29 @@ function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): T
|
||||||
return nodes;
|
return nodes;
|
||||||
}
|
}
|
||||||
|
|
||||||
function match(config: Route[], url: TreeNode<UrlSegment>): MatchResult {
|
function match(config: Route[], url: TreeNode<UrlSegment>): MatchResult[] {
|
||||||
const m = matchNonIndex(config, url);
|
const res = [];
|
||||||
if (m) return m;
|
for (let r of config) {
|
||||||
|
if (r.index) {
|
||||||
const mIndex = matchIndex(config, [url], url.value);
|
res.push(createIndexMatch(r, [url], url.value));
|
||||||
if (mIndex) return mIndex;
|
} else {
|
||||||
|
const m = matchWithParts(r, url);
|
||||||
const availableRoutes = config.map(r => {
|
if (m) res.push(m);
|
||||||
const outlet = !r.outlet ? '' : `${r.outlet}:`;
|
}
|
||||||
return `'${outlet}${r.path}'`;
|
}
|
||||||
}).join(", ");
|
return res;
|
||||||
throw new Error(
|
|
||||||
`Cannot match any routes. Current segment: '${url.value}'. Available routes: [${availableRoutes}].`);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchNonIndex(config: Route[], url: TreeNode<UrlSegment>): MatchResult | null {
|
function createIndexMatch(r: Route, leftOverUrls:TreeNode<UrlSegment>[], lastUrlSegment:UrlSegment): MatchResult {
|
||||||
for (let r of config) {
|
const outlet = r.outlet ? r.outlet : PRIMARY_OUTLET;
|
||||||
let m = matchWithParts(r, url);
|
const children = r.children ? r.children : [];
|
||||||
if (m) return m;
|
return new MatchResult(r.component, children, [], lastUrlSegment.parameters, leftOverUrls, [], outlet, r, lastUrlSegment);
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function matchIndex(config: Route[], leftOverUrls: TreeNode<UrlSegment>[], lastUrlSegment: UrlSegment): MatchResult | null {
|
function matchIndex(config: Route[], leftOverUrls: TreeNode<UrlSegment>[], lastUrlSegment: UrlSegment): MatchResult | null {
|
||||||
for (let r of config) {
|
for (let r of config) {
|
||||||
if (r.index) {
|
if (r.index) {
|
||||||
const outlet = r.outlet ? r.outlet : PRIMARY_OUTLET;
|
return createIndexMatch(r, leftOverUrls, lastUrlSegment);
|
||||||
const children = r.children ? r.children : [];
|
|
||||||
return new MatchResult(r.component, children, [], lastUrlSegment.parameters, leftOverUrls, [], outlet, r, lastUrlSegment);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -17,19 +17,6 @@ describe('recognize', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle position args', () => {
|
|
||||||
recognize(RootComponent, [
|
|
||||||
{
|
|
||||||
path: 'a/:id', component: ComponentA, children: [
|
|
||||||
{ path: 'b/:id', component: ComponentB}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
], tree("a/paramA/b/paramB")).forEach(s => {
|
|
||||||
checkActivatedRoute(s.root, "", {}, RootComponent);
|
|
||||||
checkActivatedRoute(s.firstChild(s.root), "a/paramA", {id: 'paramA'}, ComponentA);
|
|
||||||
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "b/paramB", {id: 'paramB'}, ComponentB);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
it('should support secondary routes', () => {
|
it('should support secondary routes', () => {
|
||||||
recognize(RootComponent, [
|
recognize(RootComponent, [
|
||||||
|
@ -44,6 +31,25 @@ describe('recognize', () => {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should match routes in the depth first order', () => {
|
||||||
|
recognize(RootComponent, [
|
||||||
|
{path: 'a', component: ComponentA, children: [{path: ':id', component: ComponentB}]},
|
||||||
|
{path: 'a/:id', component: ComponentC}
|
||||||
|
], tree("a/paramA")).forEach(s => {
|
||||||
|
checkActivatedRoute(s.root, "", {}, RootComponent);
|
||||||
|
checkActivatedRoute(s.firstChild(s.root), "a", {}, ComponentA);
|
||||||
|
checkActivatedRoute(s.firstChild(<any>s.firstChild(s.root)), "paramA", {id: 'paramA'}, ComponentB);
|
||||||
|
});
|
||||||
|
|
||||||
|
recognize(RootComponent, [
|
||||||
|
{path: 'a', component: ComponentA},
|
||||||
|
{path: 'a/:id', component: ComponentC}
|
||||||
|
], tree("a/paramA")).forEach(s => {
|
||||||
|
checkActivatedRoute(s.root, "", {}, RootComponent);
|
||||||
|
checkActivatedRoute(s.firstChild(s.root), "a/paramA", {id: 'paramA'}, ComponentC);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should use outlet name when matching secondary routes', () => {
|
it('should use outlet name when matching secondary routes', () => {
|
||||||
recognize(RootComponent, [
|
recognize(RootComponent, [
|
||||||
{ path: 'a', component: ComponentA },
|
{ path: 'a', component: ComponentA },
|
||||||
|
|
Loading…
Reference in New Issue