diff --git a/modules/angular2/src/router/router_link.ts b/modules/angular2/src/router/router_link.ts index 11d5687446..9fca450544 100644 --- a/modules/angular2/src/router/router_link.ts +++ b/modules/angular2/src/router/router_link.ts @@ -1,5 +1,5 @@ import {Directive} from '../core/metadata'; -import {StringMapWrapper} from 'angular2/src/core/facade/collection'; +import {isString} from 'angular2/src/core/facade/lang'; import {Router} from './router'; import {Location} from './location'; @@ -36,7 +36,7 @@ import {Instruction, stringifyInstruction} from './instruction'; */ @Directive({ selector: '[router-link]', - inputs: ['routeParams: routerLink'], + inputs: ['routeParams: routerLink', 'target: target'], host: { '(click)': 'onClick()', '[attr.href]': 'visibleHref', @@ -48,6 +48,7 @@ export class RouterLink { // the url displayed on the anchor element. visibleHref: string; + target: string; // the instruction passed to the router to navigate private _navigationInstruction: Instruction; @@ -65,7 +66,11 @@ export class RouterLink { } onClick(): boolean { - this._router.navigateByInstruction(this._navigationInstruction); - return false; + // If no target, or if target is _self, prevent default browser behavior + if (!isString(this.target) || this.target == '_self') { + this._router.navigateByInstruction(this._navigationInstruction); + return false; + } + return true; } } diff --git a/modules/angular2/test/router/router_link_spec.ts b/modules/angular2/test/router/router_link_spec.ts index 93df150286..5e5a6e5c6d 100644 --- a/modules/angular2/test/router/router_link_spec.ts +++ b/modules/angular2/test/router/router_link_spec.ts @@ -56,7 +56,8 @@ export function main() { tcb.createAsync(TestComponent) .then((testComponent) => { testComponent.detectChanges(); - let anchorElement = testComponent.debugElement.query(By.css('a')).nativeElement; + let anchorElement = + testComponent.debugElement.query(By.css('a.detail-view')).nativeElement; expect(DOM.getAttribute(anchorElement, 'href')).toEqual('detail'); async.done(); }); @@ -70,11 +71,38 @@ export function main() { .then((testComponent) => { testComponent.detectChanges(); // TODO: shouldn't this be just 'click' rather than '^click'? - testComponent.debugElement.query(By.css('a')).triggerEventHandler('click', null); + testComponent.debugElement.query(By.css('a.detail-view')) + .triggerEventHandler('click', null); expect(router.spy('navigateByInstruction')).toHaveBeenCalledWith(dummyInstruction); async.done(); }); })); + + it('should call router.navigate when a link is clicked if target is _self', + inject([AsyncTestCompleter, Router], (async, router) => { + + tcb.createAsync(TestComponent) + .then((testComponent) => { + testComponent.detectChanges(); + testComponent.debugElement.query(By.css('a.detail-view-self')) + .triggerEventHandler('click', null); + expect(router.spy('navigateByInstruction')).toHaveBeenCalledWith(dummyInstruction); + async.done(); + }); + })); + + it('should NOT call router.navigate when a link is clicked if target is set to other than _self', + inject([AsyncTestCompleter, Router], (async, router) => { + + tcb.createAsync(TestComponent) + .then((testComponent) => { + testComponent.detectChanges(); + testComponent.debugElement.query(By.css('a.detail-view-blank')) + .triggerEventHandler('click', null); + expect(router.spy('navigateByInstruction')).not.toHaveBeenCalled(); + async.done(); + }); + })); }); } @@ -94,7 +122,20 @@ class UserCmp { @View({ template: `