Skip to content

Commit cee67e6

Browse files
committed
Revert "feat(router): allow linking to auxiliary routes"
This reverts commit 0b1ff2d.
1 parent a3353a5 commit cee67e6

4 files changed

Lines changed: 62 additions & 108 deletions

File tree

modules/angular2/src/router/route_recognizer.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,6 @@ import {ComponentInstruction} from './instruction';
2626
export class RouteRecognizer {
2727
names = new Map<string, PathRecognizer>();
2828

29-
// map from name to recognizer
30-
auxNames = new Map<string, PathRecognizer>();
31-
32-
// map from starting path to recognizer
3329
auxRoutes = new Map<string, PathRecognizer>();
3430

3531
// TODO: optimize this into a trie
@@ -52,12 +48,8 @@ export class RouteRecognizer {
5248
let path = config.path.startsWith('/') ? config.path.substring(1) : config.path;
5349
var recognizer = new PathRecognizer(config.path, handler);
5450
this.auxRoutes.set(path, recognizer);
55-
if (isPresent(config.name)) {
56-
this.auxNames.set(config.name, recognizer);
57-
}
5851
return recognizer.terminal;
5952
}
60-
6153
if (config instanceof Redirect) {
6254
this.redirects.push(new Redirector(config.path, config.redirectTo));
6355
return true;
@@ -135,14 +127,6 @@ export class RouteRecognizer {
135127
}
136128
return pathRecognizer.generate(params);
137129
}
138-
139-
generateAuxiliary(name: string, params: any): ComponentInstruction {
140-
var pathRecognizer: PathRecognizer = this.auxNames.get(name);
141-
if (isBlank(pathRecognizer)) {
142-
return null;
143-
}
144-
return pathRecognizer.generate(params);
145-
}
146130
}
147131

148132
export class Redirector {

modules/angular2/src/router/route_registry.ts

Lines changed: 53 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import {ListWrapper, Map, MapWrapper, StringMapWrapper} from 'angular2/src/facad
55
import {Promise, PromiseWrapper} from 'angular2/src/facade/async';
66
import {
77
isPresent,
8-
isArray,
98
isBlank,
109
isType,
1110
isString,
@@ -189,61 +188,70 @@ export class RouteRegistry {
189188
* Given a normalized list with component names and params like: `['user', {id: 3 }]`
190189
* generates a url with a leading slash relative to the provided `parentComponent`.
191190
*/
192-
generate(linkParams: any[], parentComponent: any, _aux = false): Instruction {
193-
let linkIndex = 0;
194-
let routeName = linkParams[linkIndex];
195-
196-
// TODO: this is kind of odd but it makes existing assertions pass
197-
if (isBlank(parentComponent)) {
198-
throw new BaseException(`Could not find route named "${routeName}".`);
199-
}
200-
201-
if (!isString(routeName)) {
202-
throw new BaseException(`Unexpected segment "${routeName}" in link DSL. Expected a string.`);
203-
} else if (routeName == '' || routeName == '.' || routeName == '..') {
204-
throw new BaseException(`"${routeName}/" is only allowed at the beginning of a link DSL.`);
205-
}
191+
generate(linkParams: any[], parentComponent: any): Instruction {
192+
let segments = [];
193+
let componentCursor = parentComponent;
194+
var lastInstructionIsTerminal = false;
195+
196+
for (let i = 0; i < linkParams.length; i += 1) {
197+
let segment = linkParams[i];
198+
if (isBlank(componentCursor)) {
199+
throw new BaseException(`Could not find route named "${segment}".`);
200+
}
201+
if (!isString(segment)) {
202+
throw new BaseException(`Unexpected segment "${segment}" in link DSL. Expected a string.`);
203+
} else if (segment == '' || segment == '.' || segment == '..') {
204+
throw new BaseException(`"${segment}/" is only allowed at the beginning of a link DSL.`);
205+
}
206+
let params = {};
207+
if (i + 1 < linkParams.length) {
208+
let nextSegment = linkParams[i + 1];
209+
if (isStringMap(nextSegment)) {
210+
params = nextSegment;
211+
i += 1;
212+
}
213+
}
206214

207-
let params = {};
208-
if (linkIndex + 1 < linkParams.length) {
209-
let nextSegment = linkParams[linkIndex + 1];
210-
if (isStringMap(nextSegment) && !isArray(nextSegment)) {
211-
params = nextSegment;
212-
linkIndex += 1;
215+
var componentRecognizer = this._rules.get(componentCursor);
216+
if (isBlank(componentRecognizer)) {
217+
throw new BaseException(
218+
`Component "${getTypeNameForDebugging(componentCursor)}" has no route config.`);
213219
}
214-
}
220+
var response = componentRecognizer.generate(segment, params);
215221

216-
let auxInstructions: {[key: string]: Instruction} = {};
217-
var nextSegment;
218-
while (linkIndex + 1 < linkParams.length && isArray(nextSegment = linkParams[linkIndex + 1])) {
219-
auxInstructions[nextSegment[0]] = this.generate(nextSegment, parentComponent, true);
220-
linkIndex += 1;
222+
if (isBlank(response)) {
223+
throw new BaseException(
224+
`Component "${getTypeNameForDebugging(componentCursor)}" has no route named "${segment}".`);
225+
}
226+
segments.push(response);
227+
componentCursor = response.componentType;
228+
lastInstructionIsTerminal = response.terminal;
221229
}
222230

223-
var componentRecognizer = this._rules.get(parentComponent);
224-
if (isBlank(componentRecognizer)) {
225-
throw new BaseException(
226-
`Component "${getTypeNameForDebugging(parentComponent)}" has no route config.`);
227-
}
231+
var instruction: Instruction = null;
228232

229-
var componentInstruction = _aux ? componentRecognizer.generateAuxiliary(routeName, params) :
230-
componentRecognizer.generate(routeName, params);
233+
if (!lastInstructionIsTerminal) {
234+
instruction = this._generateRedirects(componentCursor);
231235

232-
if (isBlank(componentInstruction)) {
233-
throw new BaseException(
234-
`Component "${getTypeNameForDebugging(parentComponent)}" has no route named "${routeName}".`);
236+
if (isPresent(instruction)) {
237+
let lastInstruction = instruction;
238+
while (isPresent(lastInstruction.child)) {
239+
lastInstruction = lastInstruction.child;
240+
}
241+
lastInstructionIsTerminal = lastInstruction.component.terminal;
242+
}
243+
if (isPresent(componentCursor) && !lastInstructionIsTerminal) {
244+
throw new BaseException(
245+
`Link "${ListWrapper.toJSON(linkParams)}" does not resolve to a terminal or async instruction.`);
246+
}
235247
}
236248

237-
var childInstruction = null;
238-
if (linkIndex + 1 < linkParams.length) {
239-
var remaining = linkParams.slice(linkIndex + 1);
240-
childInstruction = this.generate(remaining, componentInstruction.componentType);
241-
} else if (!componentInstruction.terminal) {
242-
throw new BaseException(
243-
`Link "${ListWrapper.toJSON(linkParams)}" does not resolve to a terminal or async instruction.`);
249+
250+
while (segments.length > 0) {
251+
instruction = new Instruction(segments.pop(), instruction, {});
244252
}
245253

246-
return new Instruction(componentInstruction, childInstruction, auxInstructions);
254+
return instruction;
247255
}
248256

249257
public hasRoute(name: string, parentComponent: any): boolean {

modules/angular2/test/router/integration/router_link_spec.ts

Lines changed: 1 addition & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import {
3131
RouterLink,
3232
RouterOutlet,
3333
AsyncRoute,
34-
AuxRoute,
3534
Route,
3635
RouteParams,
3736
RouteConfig,
@@ -199,7 +198,7 @@ export function main() {
199198
name: 'ChildWithGrandchild'
200199
})
201200
]))
202-
.then((_) => router.navigateByUrl('/child-with-grandchild/grandchild'))
201+
.then((_) => router.navigate(['/ChildWithGrandchild']))
203202
.then((_) => {
204203
fixture.detectChanges();
205204
expect(DOM.getAttribute(fixture.debugElement.componentViewChildren[1]
@@ -235,21 +234,6 @@ export function main() {
235234
});
236235
}));
237236

238-
it('should generate links to auxiliary routes', inject([AsyncTestCompleter], (async) => {
239-
compile()
240-
.then((_) => router.config([new Route({path: '/...', component: AuxLinkCmp})]))
241-
.then((_) => router.navigateByUrl('/'))
242-
.then((_) => {
243-
rootTC.detectChanges();
244-
expect(DOM.getAttribute(rootTC.debugElement.componentViewChildren[1]
245-
.componentViewChildren[0]
246-
.nativeElement,
247-
'href'))
248-
.toEqual('/(aside)');
249-
async.done();
250-
});
251-
}));
252-
253237

254238
describe('router-link-active CSS class', () => {
255239
it('should be added to the associated element', inject([AsyncTestCompleter], (async) => {
@@ -487,17 +471,3 @@ class AmbiguousBookCmp {
487471
title: string;
488472
constructor(params: RouteParams) { this.title = params.get('title'); }
489473
}
490-
491-
@Component({selector: 'aux-cmp'})
492-
@View({
493-
template:
494-
`<a [router-link]="[\'./Hello\', [ \'Aside\' ] ]">aside</a> |
495-
<router-outlet></router-outlet> | aside <router-outlet name="aside"></router-outlet>`,
496-
directives: ROUTER_DIRECTIVES
497-
})
498-
@RouteConfig([
499-
new Route({path: '/', component: HelloCmp, name: 'Hello'}),
500-
new AuxRoute({path: '/aside', component: Hello2Cmp, name: 'Aside'})
501-
])
502-
class AuxLinkCmp {
503-
}

modules/angular2/test/router/route_registry_spec.ts

Lines changed: 8 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ export function main() {
5151
.toEqual('second');
5252
});
5353

54-
xit('should generate URLs that account for redirects', () => {
54+
it('should generate URLs that account for redirects', () => {
5555
registry.config(
5656
RootHostCmp,
5757
new Route({path: '/first/...', component: DummyParentRedirectCmp, name: 'FirstCmp'}));
@@ -60,7 +60,7 @@ export function main() {
6060
.toEqual('first/second');
6161
});
6262

63-
xit('should generate URLs in a hierarchy of redirects', () => {
63+
it('should generate URLs in a hierarchy of redirects', () => {
6464
registry.config(
6565
RootHostCmp,
6666
new Route({path: '/first/...', component: DummyMultipleRedirectCmp, name: 'FirstCmp'}));
@@ -89,7 +89,7 @@ export function main() {
8989
inject([AsyncTestCompleter], (async) => {
9090
registry.config(
9191
RootHostCmp,
92-
new AsyncRoute({path: '/first/...', loader: asyncParentLoader, name: 'FirstCmp'}));
92+
new AsyncRoute({path: '/first/...', loader: AsyncParentLoader, name: 'FirstCmp'}));
9393

9494
expect(() => registry.generate(['FirstCmp', 'SecondCmp'], RootHostCmp))
9595
.toThrowError('Could not find route named "SecondCmp".');
@@ -103,20 +103,12 @@ export function main() {
103103
});
104104
}));
105105

106+
106107
it('should throw when generating a url and a parent has no config', () => {
107108
expect(() => registry.generate(['FirstCmp', 'SecondCmp'], RootHostCmp))
108109
.toThrowError('Component "RootHostCmp" has no route config.');
109110
});
110111

111-
it('should generate URLs for aux routes', () => {
112-
registry.config(RootHostCmp,
113-
new Route({path: '/primary', component: DummyCmpA, name: 'Primary'}));
114-
registry.config(RootHostCmp, new AuxRoute({path: '/aux', component: DummyCmpB, name: 'Aux'}));
115-
116-
expect(stringifyInstruction(registry.generate(['Primary', ['Aux']], RootHostCmp)))
117-
.toEqual('primary(aux)');
118-
});
119-
120112
it('should prefer static segments to dynamic', inject([AsyncTestCompleter], (async) => {
121113
registry.config(RootHostCmp, new Route({path: '/:site', component: DummyCmpB}));
122114
registry.config(RootHostCmp, new Route({path: '/home', component: DummyCmpA}));
@@ -201,7 +193,7 @@ export function main() {
201193
it('should match the URL using an async parent component',
202194
inject([AsyncTestCompleter], (async) => {
203195
registry.config(RootHostCmp,
204-
new AsyncRoute({path: '/first/...', loader: asyncParentLoader}));
196+
new AsyncRoute({path: '/first/...', loader: AsyncParentLoader}));
205197

206198
registry.recognize('/first/second', RootHostCmp)
207199
.then((instruction) => {
@@ -283,17 +275,17 @@ export function main() {
283275
});
284276
}
285277

286-
function asyncParentLoader() {
278+
function AsyncParentLoader() {
287279
return PromiseWrapper.resolve(DummyParentCmp);
288280
}
289281

290-
function asyncChildLoader() {
282+
function AsyncChildLoader() {
291283
return PromiseWrapper.resolve(DummyCmpB);
292284
}
293285

294286
class RootHostCmp {}
295287

296-
@RouteConfig([new AsyncRoute({path: '/second', loader: asyncChildLoader})])
288+
@RouteConfig([new AsyncRoute({path: '/second', loader: AsyncChildLoader})])
297289
class DummyAsyncCmp {
298290
}
299291

0 commit comments

Comments
 (0)