parent
793ac3f6b4
commit
9b356d9b86
|
@ -7,6 +7,8 @@ import { RouterConfig, Route } from './config';
|
|||
import { Type } from '@angular/core';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
class CannotRecognize {}
|
||||
|
||||
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, url.root);
|
||||
|
@ -17,9 +19,13 @@ export function recognize(rootComponentType: Type, config: RouterConfig, url: Ur
|
|||
obs.complete();
|
||||
});
|
||||
} 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function constructActivatedRoute(match: MatchResult): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
const activatedRoute = createActivatedRouteSnapshot(match);
|
||||
|
@ -49,12 +55,21 @@ function createActivatedRouteSnapshot(match: MatchResult): ActivatedRouteSnapsho
|
|||
}
|
||||
|
||||
function recognizeOne(config: Route[], url: TreeNode<UrlSegment>): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
const m = match(config, url);
|
||||
const primary = constructActivatedRoute(m);
|
||||
const secondary = recognizeMany(config, m.secondary);
|
||||
const matches = match(config, url);
|
||||
for(let match of matches) {
|
||||
try {
|
||||
const primary = constructActivatedRoute(match);
|
||||
const secondary = recognizeMany(config, match.secondary);
|
||||
const res = primary.concat(secondary);
|
||||
checkOutletNameUniqueness(res);
|
||||
return res;
|
||||
} catch (e) {
|
||||
if (! (e instanceof CannotRecognize)) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw new CannotRecognize();
|
||||
}
|
||||
|
||||
function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): TreeNode<ActivatedRouteSnapshot>[] {
|
||||
|
@ -71,35 +86,29 @@ function checkOutletNameUniqueness(nodes: TreeNode<ActivatedRouteSnapshot>[]): T
|
|||
return nodes;
|
||||
}
|
||||
|
||||
function match(config: Route[], url: TreeNode<UrlSegment>): MatchResult {
|
||||
const m = matchNonIndex(config, url);
|
||||
if (m) return m;
|
||||
|
||||
const mIndex = matchIndex(config, [url], url.value);
|
||||
if (mIndex) return mIndex;
|
||||
|
||||
const availableRoutes = config.map(r => {
|
||||
const outlet = !r.outlet ? '' : `${r.outlet}:`;
|
||||
return `'${outlet}${r.path}'`;
|
||||
}).join(", ");
|
||||
throw new Error(
|
||||
`Cannot match any routes. Current segment: '${url.value}'. Available routes: [${availableRoutes}].`);
|
||||
}
|
||||
|
||||
function matchNonIndex(config: Route[], url: TreeNode<UrlSegment>): MatchResult | null {
|
||||
function match(config: Route[], url: TreeNode<UrlSegment>): MatchResult[] {
|
||||
const res = [];
|
||||
for (let r of config) {
|
||||
let m = matchWithParts(r, url);
|
||||
if (m) return m;
|
||||
if (r.index) {
|
||||
res.push(createIndexMatch(r, [url], url.value));
|
||||
} else {
|
||||
const m = matchWithParts(r, url);
|
||||
if (m) res.push(m);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
function createIndexMatch(r: Route, leftOverUrls:TreeNode<UrlSegment>[], lastUrlSegment:UrlSegment): MatchResult {
|
||||
const outlet = r.outlet ? r.outlet : PRIMARY_OUTLET;
|
||||
const children = r.children ? r.children : [];
|
||||
return new MatchResult(r.component, children, [], lastUrlSegment.parameters, leftOverUrls, [], outlet, r, lastUrlSegment);
|
||||
}
|
||||
|
||||
function matchIndex(config: Route[], leftOverUrls: TreeNode<UrlSegment>[], lastUrlSegment: UrlSegment): MatchResult | null {
|
||||
for (let r of config) {
|
||||
if (r.index) {
|
||||
const outlet = r.outlet ? r.outlet : PRIMARY_OUTLET;
|
||||
const children = r.children ? r.children : [];
|
||||
return new MatchResult(r.component, children, [], lastUrlSegment.parameters, leftOverUrls, [], outlet, r, lastUrlSegment);
|
||||
return createIndexMatch(r, leftOverUrls, lastUrlSegment);
|
||||
}
|
||||
}
|
||||
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', () => {
|
||||
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', () => {
|
||||
recognize(RootComponent, [
|
||||
{ path: 'a', component: ComponentA },
|
||||
|
|
Loading…
Reference in New Issue