Skip to content

Commit c452832

Browse files
committed
fix(router): router link should navigate to non-base Url.
While still displaying full base + custom part of url in the href.
1 parent 826af40 commit c452832

File tree

3 files changed

+73
-29
lines changed

3 files changed

+73
-29
lines changed

modules/angular2/src/mock/location_mock.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ export class SpyLocation extends SpyObject {
4545
}
4646

4747
go(url:string) {
48-
if (this._path === url) {
48+
url = this.normalizeAbsolutely(url);
49+
if (this._path == url) {
4950
return;
5051
}
5152
this._path = url;

modules/angular2/src/router/router_link.js

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,10 @@ export class RouterLink {
4343
_params:StringMap<string, string>;
4444
_router:Router;
4545
_location:Location;
46-
_href:string;
46+
// the url displayed on the anchor element.
47+
_visibleHref: string;
48+
// the url passed to the router navigation.
49+
_navigationHref: string;
4750

4851
constructor(elementRef:ElementRef, router:Router, location:Location) {
4952
this._domEl = elementRef.domElement;
@@ -52,7 +55,7 @@ export class RouterLink {
5255
this._params = StringMapWrapper.create();
5356
DOM.on(this._domEl, 'click', (evt) => {
5457
evt.preventDefault();
55-
this._router.navigate(this._href);
58+
this._router.navigate(this._navigationHref);
5659
});
5760
}
5861

@@ -66,11 +69,11 @@ export class RouterLink {
6669

6770
onAllChangesDone(): void {
6871
if (isPresent(this._route) && isPresent(this._params)) {
69-
var newHref = this._router.generate(this._route, this._params);
70-
this._href = this._location.normalizeAbsolutely(newHref);
72+
this._navigationHref = this._router.generate(this._route, this._params);
73+
this._visibleHref = this._location.normalizeAbsolutely(this._navigationHref);
7174
// Keeping the link on the element to support contextual menu `copy link`
7275
// and other in-browser affordances.
73-
DOM.setAttribute(this._domEl, 'href', this._href);
76+
DOM.setAttribute(this._domEl, 'href', this._visibleHref);
7477
}
7578
}
7679
}

modules/angular2/test/router/outlet_spec.js

Lines changed: 63 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,9 @@ export function main() {
135135
});
136136
}));
137137

138+
function getHref(view) {
139+
return DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href');
140+
}
138141

139142
it('should generate absolute hrefs that include the base href', inject([AsyncTestCompleter], (async) => {
140143
location.setBaseHref('/my/base');
@@ -143,7 +146,7 @@ export function main() {
143146
.then((_) => rtr.navigate('/a/b'))
144147
.then((_) => {
145148
view.detectChanges();
146-
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/my/base/user');
149+
expect(getHref(view)).toEqual('/my/base/user');
147150
async.done();
148151
});
149152
}));
@@ -155,13 +158,13 @@ export function main() {
155158
.then((_) => rtr.navigate('/a/b'))
156159
.then((_) => {
157160
view.detectChanges();
158-
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/user');
161+
expect(getHref(view)).toEqual('/user');
159162
async.done();
160163
});
161164
}));
162165

163166

164-
it('should reuse common parent components', inject([AsyncTestCompleter, Location], (async, location) => {
167+
it('should reuse common parent components', inject([AsyncTestCompleter], (async) => {
165168
compile()
166169
.then((_) => rtr.config({'path': '/team/:id', 'component': TeamCmp }))
167170
.then((_) => rtr.navigate('/team/angular/user/rado'))
@@ -193,27 +196,64 @@ export function main() {
193196
});
194197
}));
195198

196-
197-
it('should generate link hrefs without params', inject([AsyncTestCompleter], (async) => {
198-
compile('<a href="hello" router-link="user"></a>')
199-
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
200-
.then((_) => rtr.navigate('/a/b'))
201-
.then((_) => {
202-
view.detectChanges();
203-
var anchorEl = view.rootNodes[0].childNodes[0];
204-
expect(DOM.getAttribute(anchorEl, 'href')).toEqual('/user');
205-
206-
var dispatchedEvent = DOM.createMouseEvent('click');
207-
DOM.dispatchEvent(anchorEl, dispatchedEvent);
208-
expect(dispatchedEvent.defaultPrevented).toBe(true);
209-
210-
// router navigation is async.
211-
rtr.subscribe((_) => {
212-
expect(location.urlChanges).toEqual(['/user']);
213-
async.done();
199+
describe('when clicked', () => {
200+
201+
var clickOnElement = function(view) {
202+
var anchorEl = view.rootNodes[0].childNodes[0];
203+
var dispatchedEvent = DOM.createMouseEvent('click');
204+
DOM.dispatchEvent(anchorEl, dispatchedEvent);
205+
return dispatchedEvent;
206+
};
207+
208+
it('test', inject([AsyncTestCompleter], (async) => {
209+
async.done();
210+
}));
211+
212+
it('should navigate to link hrefs without params', inject([AsyncTestCompleter], (async) => {
213+
compile('<a href="hello" router-link="user"></a>')
214+
.then((_) => rtr.config({
215+
'path': '/user',
216+
'component': UserCmp,
217+
'as': 'user'
218+
}))
219+
.then((_) => rtr.navigate('/a/b'))
220+
.then((_) => {
221+
view.detectChanges();
222+
223+
var dispatchedEvent = clickOnElement(view);
224+
expect(dispatchedEvent.defaultPrevented).toBe(true);
225+
226+
// router navigation is async.
227+
rtr.subscribe((_) => {
228+
expect(location.urlChanges).toEqual(['/user']);
229+
async.done();
230+
});
214231
});
215-
});
216-
}));
232+
}));
233+
234+
it('should navigate to link hrefs in presence of base href', inject([AsyncTestCompleter], (async) => {
235+
location.setBaseHref('/base');
236+
compile('<a href="hello" router-link="user"></a>')
237+
.then((_) => rtr.config({
238+
'path': '/user',
239+
'component': UserCmp,
240+
'as': 'user'
241+
}))
242+
.then((_) => rtr.navigate('/a/b'))
243+
.then((_) => {
244+
view.detectChanges();
245+
246+
var dispatchedEvent = clickOnElement(view);
247+
expect(dispatchedEvent.defaultPrevented).toBe(true);
248+
249+
// router navigation is async.
250+
rtr.subscribe((_) => {
251+
expect(location.urlChanges).toEqual(['/base/user']);
252+
async.done();
253+
});
254+
});
255+
}));
256+
});
217257
});
218258
}
219259

0 commit comments

Comments
 (0)