feat(router): add queryParams and fragment to every activated route

This commit is contained in:
vsavkin
2016-08-02 15:31:56 -07:00
committed by Alex Rickabaugh
parent 550ab31bd0
commit 422d380b3e
8 changed files with 192 additions and 181 deletions

View File

@ -40,47 +40,131 @@ class InheritedFromParent {
export function recognize(rootComponentType: Type, config: Routes, urlTree: UrlTree, url: string):
Observable<RouterStateSnapshot> {
try {
const rootSegmentGroup = split(urlTree.root, [], [], config).segmentGroup;
const children = processSegmentGroup(
config, rootSegmentGroup, InheritedFromParent.empty(null), PRIMARY_OUTLET);
const root = new ActivatedRouteSnapshot(
[], Object.freeze({}), {}, PRIMARY_OUTLET, rootComponentType, null, urlTree.root, -1,
InheritedResolve.empty);
const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children);
return of (new RouterStateSnapshot(
url, rootNode, Object.freeze(urlTree.queryParams), urlTree.fragment));
} catch (e) {
if (e instanceof NoMatch) {
return new Observable<RouterStateSnapshot>(
(obs: Observer<RouterStateSnapshot>) =>
obs.error(new Error(`Cannot match any routes: '${e.segmentGroup}'`)));
} else {
return new Observable<RouterStateSnapshot>(
(obs: Observer<RouterStateSnapshot>) => obs.error(e));
return new Recognizer(rootComponentType, config, urlTree, url).recognize();
}
class Recognizer {
constructor(
private rootComponentType: Type, private config: Routes, private urlTree: UrlTree,
private url: string) {}
recognize(): Observable<RouterStateSnapshot> {
try {
const rootSegmentGroup = split(this.urlTree.root, [], [], this.config).segmentGroup;
const children = this.processSegmentGroup(
this.config, rootSegmentGroup, InheritedFromParent.empty(null), PRIMARY_OUTLET);
const root = new ActivatedRouteSnapshot(
[], Object.freeze({}), Object.freeze(this.urlTree.queryParams), this.urlTree.fragment, {},
PRIMARY_OUTLET, this.rootComponentType, null, this.urlTree.root, -1,
InheritedResolve.empty);
const rootNode = new TreeNode<ActivatedRouteSnapshot>(root, children);
return of (new RouterStateSnapshot(this.url, rootNode));
} catch (e) {
if (e instanceof NoMatch) {
return new Observable<RouterStateSnapshot>(
(obs: Observer<RouterStateSnapshot>) =>
obs.error(new Error(`Cannot match any routes: '${e.segmentGroup}'`)));
} else {
return new Observable<RouterStateSnapshot>(
(obs: Observer<RouterStateSnapshot>) => obs.error(e));
}
}
}
}
function processSegmentGroup(
config: Route[], segmentGroup: UrlSegmentGroup, inherited: InheritedFromParent,
outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return processChildren(config, segmentGroup, inherited);
} else {
return processSegment(config, segmentGroup, 0, segmentGroup.segments, inherited, outlet);
processSegmentGroup(
config: Route[], segmentGroup: UrlSegmentGroup, inherited: InheritedFromParent,
outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
if (segmentGroup.segments.length === 0 && segmentGroup.hasChildren()) {
return this.processChildren(config, segmentGroup, inherited);
} else {
return this.processSegment(config, segmentGroup, 0, segmentGroup.segments, inherited, outlet);
}
}
}
function processChildren(
config: Route[], segmentGroup: UrlSegmentGroup,
inherited: InheritedFromParent): TreeNode<ActivatedRouteSnapshot>[] {
const children = mapChildrenIntoArray(
segmentGroup,
(child, childOutlet) => processSegmentGroup(config, child, inherited, childOutlet));
checkOutletNameUniqueness(children);
sortActivatedRouteSnapshots(children);
return children;
processChildren(config: Route[], segmentGroup: UrlSegmentGroup, inherited: InheritedFromParent):
TreeNode<ActivatedRouteSnapshot>[] {
const children = mapChildrenIntoArray(
segmentGroup,
(child, childOutlet) => this.processSegmentGroup(config, child, inherited, childOutlet));
checkOutletNameUniqueness(children);
sortActivatedRouteSnapshots(children);
return children;
}
processSegment(
config: Route[], segmentGroup: UrlSegmentGroup, pathIndex: number, segments: UrlSegment[],
inherited: InheritedFromParent, outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
for (let r of config) {
try {
return this.processSegmentAgainstRoute(
r, segmentGroup, pathIndex, segments, inherited, outlet);
} catch (e) {
if (!(e instanceof NoMatch)) throw e;
}
}
throw new NoMatch(segmentGroup);
}
processSegmentAgainstRoute(
route: Route, rawSegment: UrlSegmentGroup, pathIndex: number, segments: UrlSegment[],
inherited: InheritedFromParent, outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
if (route.redirectTo) throw new NoMatch();
if ((route.outlet ? route.outlet : PRIMARY_OUTLET) !== outlet) throw new NoMatch();
const newInheritedResolve = new InheritedResolve(inherited.resolve, getResolve(route));
if (route.path === '**') {
const params = segments.length > 0 ? last(segments).parameters : {};
const snapshot = new ActivatedRouteSnapshot(
segments, Object.freeze(merge(inherited.allParams, params)),
Object.freeze(this.urlTree.queryParams), this.urlTree.fragment,
merge(inherited.allData, getData(route)), outlet, route.component, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length,
newInheritedResolve);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
}
const {consumedSegments, parameters, lastChild} =
match(rawSegment, route, segments, inherited.snapshot);
const rawSlicedSegments = segments.slice(lastChild);
const childConfig = getChildConfig(route);
const {segmentGroup, slicedSegments} =
split(rawSegment, consumedSegments, rawSlicedSegments, childConfig);
const snapshot = new ActivatedRouteSnapshot(
consumedSegments, Object.freeze(merge(inherited.allParams, parameters)),
Object.freeze(this.urlTree.queryParams), this.urlTree.fragment,
merge(inherited.allData, getData(route)), outlet, route.component, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length,
newInheritedResolve);
const newInherited = route.component ?
InheritedFromParent.empty(snapshot) :
new InheritedFromParent(
inherited, snapshot, parameters, getData(route), newInheritedResolve);
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
const children = this.processChildren(childConfig, segmentGroup, newInherited);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];
} else if (childConfig.length === 0 && slicedSegments.length === 0) {
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
} else {
const children = this.processSegment(
childConfig, segmentGroup, pathIndex + lastChild, slicedSegments, newInherited,
PRIMARY_OUTLET);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];
}
}
}
function sortActivatedRouteSnapshots(nodes: TreeNode<ActivatedRouteSnapshot>[]): void {
@ -91,71 +175,6 @@ function sortActivatedRouteSnapshots(nodes: TreeNode<ActivatedRouteSnapshot>[]):
});
}
function processSegment(
config: Route[], segmentGroup: UrlSegmentGroup, pathIndex: number, segments: UrlSegment[],
inherited: InheritedFromParent, outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
for (let r of config) {
try {
return processSegmentAgainstRoute(r, segmentGroup, pathIndex, segments, inherited, outlet);
} catch (e) {
if (!(e instanceof NoMatch)) throw e;
}
}
throw new NoMatch(segmentGroup);
}
function processSegmentAgainstRoute(
route: Route, rawSegment: UrlSegmentGroup, pathIndex: number, segments: UrlSegment[],
inherited: InheritedFromParent, outlet: string): TreeNode<ActivatedRouteSnapshot>[] {
if (route.redirectTo) throw new NoMatch();
if ((route.outlet ? route.outlet : PRIMARY_OUTLET) !== outlet) throw new NoMatch();
const newInheritedResolve = new InheritedResolve(inherited.resolve, getResolve(route));
if (route.path === '**') {
const params = segments.length > 0 ? last(segments).parameters : {};
const snapshot = new ActivatedRouteSnapshot(
segments, Object.freeze(merge(inherited.allParams, params)),
merge(inherited.allData, getData(route)), outlet, route.component, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + segments.length,
newInheritedResolve);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
}
const {consumedSegments, parameters, lastChild} =
match(rawSegment, route, segments, inherited.snapshot);
const rawSlicedSegments = segments.slice(lastChild);
const childConfig = getChildConfig(route);
const {segmentGroup, slicedSegments} =
split(rawSegment, consumedSegments, rawSlicedSegments, childConfig);
const snapshot = new ActivatedRouteSnapshot(
consumedSegments, Object.freeze(merge(inherited.allParams, parameters)),
merge(inherited.allData, getData(route)), outlet, route.component, route,
getSourceSegmentGroup(rawSegment), getPathIndexShift(rawSegment) + consumedSegments.length,
newInheritedResolve);
const newInherited = route.component ?
InheritedFromParent.empty(snapshot) :
new InheritedFromParent(inherited, snapshot, parameters, getData(route), newInheritedResolve);
if (slicedSegments.length === 0 && segmentGroup.hasChildren()) {
const children = processChildren(childConfig, segmentGroup, newInherited);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];
} else if (childConfig.length === 0 && slicedSegments.length === 0) {
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, [])];
} else {
const children = processSegment(
childConfig, segmentGroup, pathIndex + lastChild, slicedSegments, newInherited,
PRIMARY_OUTLET);
return [new TreeNode<ActivatedRouteSnapshot>(snapshot, children)];
}
}
function getChildConfig(route: Route): Route[] {
if (route.children) {
return route.children;