Skip to content

Commit fa5bfe4

Browse files
committed
feat(router): add link that support only absolute urls
1 parent 446657b commit fa5bfe4

File tree

2 files changed

+131
-0
lines changed

2 files changed

+131
-0
lines changed
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import {Tree, TreeNode, UrlSegment, RouteSegment, rootNode} from './segments';
2+
import {isBlank, isString, isStringMap} from 'angular2/src/facade/lang';
3+
import {ListWrapper} from 'angular2/src/facade/collection';
4+
5+
export function link(segment: RouteSegment, tree: Tree<UrlSegment>,
6+
change: any[]): Tree<UrlSegment> {
7+
if (change.length === 0) return tree;
8+
let normalizedChange = (change.length === 1 && change[0] == "/") ? change : ["/"].concat(change);
9+
return new Tree<UrlSegment>(_update(rootNode(tree), normalizedChange));
10+
}
11+
12+
function _update(node: TreeNode<UrlSegment>, changes: any[]): TreeNode<UrlSegment> {
13+
let rest = changes.slice(1);
14+
let outlet = _outlet(changes);
15+
let segment = _segment(changes);
16+
if (isString(segment) && segment[0] == "/") segment = segment.substring(1);
17+
18+
// reach the end of the tree => create new tree nodes.
19+
if (isBlank(node)) {
20+
let urlSegment = new UrlSegment(segment, null, outlet);
21+
let children = rest.length === 0 ? [] : [_update(null, rest)];
22+
return new TreeNode<UrlSegment>(urlSegment, children);
23+
24+
// different outlet => preserve the subtree
25+
} else if (outlet != node.value.outlet) {
26+
return node;
27+
28+
// same outlet => modify the subtree
29+
} else {
30+
let urlSegment = isStringMap(segment) ? new UrlSegment(null, segment, null) :
31+
new UrlSegment(segment, null, outlet);
32+
if (rest.length === 0) {
33+
return new TreeNode<UrlSegment>(urlSegment, []);
34+
}
35+
36+
return new TreeNode<UrlSegment>(urlSegment,
37+
_updateMany(ListWrapper.clone(node.children), rest));
38+
}
39+
}
40+
41+
function _updateMany(nodes: TreeNode<UrlSegment>[], changes: any[]): TreeNode<UrlSegment>[] {
42+
let outlet = _outlet(changes);
43+
let nodesInRightOutlet = nodes.filter(c => c.value.outlet == outlet);
44+
if (nodesInRightOutlet.length > 0) {
45+
let nodeRightOutlet = nodesInRightOutlet[0]; // there can be only one
46+
nodes[nodes.indexOf(nodeRightOutlet)] = _update(nodeRightOutlet, changes);
47+
} else {
48+
nodes.push(_update(null, changes));
49+
}
50+
51+
return nodes;
52+
}
53+
54+
function _segment(changes: any[]): any {
55+
if (!isString(changes[0])) return changes[0];
56+
let parts = changes[0].toString().split(":");
57+
return parts.length > 1 ? parts[1] : changes[0];
58+
}
59+
60+
function _outlet(changes: any[]): string {
61+
if (!isString(changes[0])) return null;
62+
let parts = changes[0].toString().split(":");
63+
return parts.length > 1 ? parts[0] : null;
64+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
import {
2+
ComponentFixture,
3+
AsyncTestCompleter,
4+
TestComponentBuilder,
5+
beforeEach,
6+
ddescribe,
7+
xdescribe,
8+
describe,
9+
el,
10+
expect,
11+
iit,
12+
inject,
13+
beforeEachProviders,
14+
it,
15+
xit
16+
} from 'angular2/testing_internal';
17+
18+
import {RouteSegment, UrlSegment, Tree} from 'angular2/src/alt_router/segments';
19+
import {link} from 'angular2/src/alt_router/link';
20+
import {DefaultRouterUrlSerializer} from 'angular2/src/alt_router/router_url_serializer';
21+
22+
export function main() {
23+
describe('link', () => {
24+
let parser = new DefaultRouterUrlSerializer();
25+
26+
it("should return the original tree when given an empty array", () => {
27+
let p = parser.parse("/");
28+
let t = link(s(p.root), p, []);
29+
expect(t).toBe(p);
30+
});
31+
32+
it("should support going to root", () => {
33+
let p = parser.parse("/");
34+
let t = link(s(p.root), p, ["/"]);
35+
expect(parser.serialize(t)).toEqual("");
36+
});
37+
38+
it("should support positional params", () => {
39+
let p = parser.parse("/");
40+
let t = link(s(p.root), p, ["/one", 11, "two", 22]);
41+
expect(parser.serialize(t)).toEqual("/one/11/two/22");
42+
});
43+
44+
it("should preserve route siblings when changing the main route", () => {
45+
let p = parser.parse("/a/11/b(c)");
46+
let t = link(s(p.root), p, ["/a", 11, 'd']);
47+
expect(parser.serialize(t)).toEqual("/a/11/d(aux:c)");
48+
});
49+
50+
it("should preserve route siblings when changing a aux route", () => {
51+
let p = parser.parse("/a/11/b(c)");
52+
let t = link(s(p.root), p, ["/a", 11, 'aux:d']);
53+
expect(parser.serialize(t)).toEqual("/a/11/b(aux:d)");
54+
});
55+
56+
57+
it('should update parameters', () => {
58+
let p = parser.parse("/a;aa=11");
59+
let t = link(s(p.root), p, ["/a", {aa: 22, bb: 33}]);
60+
expect(parser.serialize(t)).toEqual("/a;aa=22;bb=33");
61+
});
62+
});
63+
}
64+
65+
function s(u: UrlSegment): RouteSegment {
66+
return new RouteSegment([u], {}, null, null, null);
67+
}

0 commit comments

Comments
 (0)