fix(router): router link should navigate to non-base Url.

While still displaying full base + custom part of url in the href.
This commit is contained in:
Rado Kirov 2015-05-19 23:14:10 -07:00
parent 826af401a9
commit c45283216f
3 changed files with 70 additions and 26 deletions

View File

@ -45,7 +45,8 @@ export class SpyLocation extends SpyObject {
}
go(url:string) {
if (this._path === url) {
url = this.normalizeAbsolutely(url);
if (this._path == url) {
return;
}
this._path = url;

View File

@ -43,7 +43,10 @@ export class RouterLink {
_params:StringMap<string, string>;
_router:Router;
_location:Location;
_href:string;
// the url displayed on the anchor element.
_visibleHref: string;
// the url passed to the router navigation.
_navigationHref: string;
constructor(elementRef:ElementRef, router:Router, location:Location) {
this._domEl = elementRef.domElement;
@ -52,7 +55,7 @@ export class RouterLink {
this._params = StringMapWrapper.create();
DOM.on(this._domEl, 'click', (evt) => {
evt.preventDefault();
this._router.navigate(this._href);
this._router.navigate(this._navigationHref);
});
}
@ -66,11 +69,11 @@ export class RouterLink {
onAllChangesDone(): void {
if (isPresent(this._route) && isPresent(this._params)) {
var newHref = this._router.generate(this._route, this._params);
this._href = this._location.normalizeAbsolutely(newHref);
this._navigationHref = this._router.generate(this._route, this._params);
this._visibleHref = this._location.normalizeAbsolutely(this._navigationHref);
// Keeping the link on the element to support contextual menu `copy link`
// and other in-browser affordances.
DOM.setAttribute(this._domEl, 'href', this._href);
DOM.setAttribute(this._domEl, 'href', this._visibleHref);
}
}
}

View File

@ -135,6 +135,9 @@ export function main() {
});
}));
function getHref(view) {
return DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href');
}
it('should generate absolute hrefs that include the base href', inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/my/base');
@ -143,7 +146,7 @@ export function main() {
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/my/base/user');
expect(getHref(view)).toEqual('/my/base/user');
async.done();
});
}));
@ -155,13 +158,13 @@ export function main() {
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
expect(DOM.getAttribute(view.rootNodes[0].childNodes[0], 'href')).toEqual('/user');
expect(getHref(view)).toEqual('/user');
async.done();
});
}));
it('should reuse common parent components', inject([AsyncTestCompleter, Location], (async, location) => {
it('should reuse common parent components', inject([AsyncTestCompleter], (async) => {
compile()
.then((_) => rtr.config({'path': '/team/:id', 'component': TeamCmp }))
.then((_) => rtr.navigate('/team/angular/user/rado'))
@ -193,27 +196,64 @@ export function main() {
});
}));
describe('when clicked', () => {
it('should generate link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({'path': '/user', 'component': UserCmp, 'as': 'user'}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var anchorEl = view.rootNodes[0].childNodes[0];
expect(DOM.getAttribute(anchorEl, 'href')).toEqual('/user');
var clickOnElement = function(view) {
var anchorEl = view.rootNodes[0].childNodes[0];
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
return dispatchedEvent;
};
var dispatchedEvent = DOM.createMouseEvent('click');
DOM.dispatchEvent(anchorEl, dispatchedEvent);
expect(dispatchedEvent.defaultPrevented).toBe(true);
it('test', inject([AsyncTestCompleter], (async) => {
async.done();
}));
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/user']);
async.done();
it('should navigate to link hrefs without params', inject([AsyncTestCompleter], (async) => {
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({
'path': '/user',
'component': UserCmp,
'as': 'user'
}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented).toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/user']);
async.done();
});
});
});
}));
}));
it('should navigate to link hrefs in presence of base href', inject([AsyncTestCompleter], (async) => {
location.setBaseHref('/base');
compile('<a href="hello" router-link="user"></a>')
.then((_) => rtr.config({
'path': '/user',
'component': UserCmp,
'as': 'user'
}))
.then((_) => rtr.navigate('/a/b'))
.then((_) => {
view.detectChanges();
var dispatchedEvent = clickOnElement(view);
expect(dispatchedEvent.defaultPrevented).toBe(true);
// router navigation is async.
rtr.subscribe((_) => {
expect(location.urlChanges).toEqual(['/base/user']);
async.done();
});
});
}));
});
});
}