fix(router): openning links in new tab
Clicks on router-link should not prevent browser default action when any mouse button other than left mouse button or ctrl/meta key is pressed. router-link href should use location strategy external url. Closes #5908 Closes #6806 Closes #7749 Closes #8806 Closes #8821
This commit is contained in:
parent
172a5663ef
commit
fa2ce8100b
|
@ -3,6 +3,7 @@ import {Router} from '../router';
|
||||||
import {RouteSegment} from '../segments';
|
import {RouteSegment} from '../segments';
|
||||||
import {isString, isArray, isPresent} from '../facade/lang';
|
import {isString, isArray, isPresent} from '../facade/lang';
|
||||||
import {ObservableWrapper} from '../facade/async';
|
import {ObservableWrapper} from '../facade/async';
|
||||||
|
import {LocationStrategy} from '@angular/common';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The RouterLink directive lets you link to specific parts of your app.
|
* The RouterLink directive lets you link to specific parts of your app.
|
||||||
|
@ -44,7 +45,8 @@ export class RouterLink implements OnDestroy {
|
||||||
@HostBinding() href: string;
|
@HostBinding() href: string;
|
||||||
@HostBinding('class.router-link-active') isActive: boolean = false;
|
@HostBinding('class.router-link-active') isActive: boolean = false;
|
||||||
|
|
||||||
constructor(private _routeSegment: RouteSegment, private _router: Router) {
|
constructor(private _routeSegment: RouteSegment, private _router: Router,
|
||||||
|
private _locationStrategy: LocationStrategy) {
|
||||||
// because auxiliary links take existing primary and auxiliary routes into account,
|
// because auxiliary links take existing primary and auxiliary routes into account,
|
||||||
// we need to update the link whenever params or other routes change.
|
// we need to update the link whenever params or other routes change.
|
||||||
this._subscription =
|
this._subscription =
|
||||||
|
@ -64,20 +66,24 @@ export class RouterLink implements OnDestroy {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@HostListener("click")
|
@HostListener("click", ["$event.button", "$event.ctrlKey", "$event.metaKey"])
|
||||||
onClick(): boolean {
|
onClick(button: number, ctrlKey: boolean, metaKey: boolean): boolean {
|
||||||
// If no target, or if target is _self, prevent default browser behavior
|
if (button != 0 || ctrlKey || metaKey) {
|
||||||
if (!isString(this.target) || this.target == '_self') {
|
return true;
|
||||||
this._router.navigate(this._commands, this._routeSegment);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
if (isString(this.target) && this.target != '_self') {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._router.navigate(this._commands, this._routeSegment);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _updateTargetUrlAndHref(): void {
|
private _updateTargetUrlAndHref(): void {
|
||||||
let tree = this._router.createUrlTree(this._commands, this._routeSegment);
|
let tree = this._router.createUrlTree(this._commands, this._routeSegment);
|
||||||
if (isPresent(tree)) {
|
if (isPresent(tree)) {
|
||||||
this.href = this._router.serializeUrl(tree);
|
this.href = this._locationStrategy.prepareExternalUrl(this._router.serializeUrl(tree));
|
||||||
this.isActive = this._router.urlTree.contains(tree);
|
this.isActive = this._router.urlTree.contains(tree);
|
||||||
} else {
|
} else {
|
||||||
this.isActive = false;
|
this.isActive = false;
|
||||||
|
|
|
@ -26,8 +26,8 @@ import {
|
||||||
OnActivate,
|
OnActivate,
|
||||||
CanDeactivate
|
CanDeactivate
|
||||||
} from '@angular/router';
|
} from '@angular/router';
|
||||||
import {Location} from '@angular/common';
|
import {Location, LocationStrategy} from '@angular/common';
|
||||||
import {SpyLocation} from '@angular/common/testing';
|
import {SpyLocation, MockLocationStrategy} from '@angular/common/testing';
|
||||||
|
|
||||||
export function main() {
|
export function main() {
|
||||||
describe('RouterLink', () => {
|
describe('RouterLink', () => {
|
||||||
|
@ -35,6 +35,7 @@ export function main() {
|
||||||
provide(RouterUrlSerializer, {useClass: DefaultRouterUrlSerializer}),
|
provide(RouterUrlSerializer, {useClass: DefaultRouterUrlSerializer}),
|
||||||
RouterOutletMap,
|
RouterOutletMap,
|
||||||
provide(Location, {useClass: SpyLocation}),
|
provide(Location, {useClass: SpyLocation}),
|
||||||
|
provide(LocationStrategy, {useClass: MockLocationStrategy}),
|
||||||
provide(Router,
|
provide(Router,
|
||||||
{
|
{
|
||||||
useFactory: (resolver, urlParser, outletMap, location) => new Router(
|
useFactory: (resolver, urlParser, outletMap, location) => new Router(
|
||||||
|
@ -44,14 +45,14 @@ export function main() {
|
||||||
]);
|
]);
|
||||||
|
|
||||||
describe("routerLink=", () => {
|
describe("routerLink=", () => {
|
||||||
it("should accept an array of commands", inject([Router], (router) => {
|
it("should accept an array of commands", inject([Router, LocationStrategy], (router, locationStrategy) => {
|
||||||
let link = new RouterLink(null, router);
|
let link = new RouterLink(null, router, locationStrategy);
|
||||||
link.routerLink = ['/one', 11];
|
link.routerLink = ['/one', 11];
|
||||||
expect(link.href).toEqual("/one/11");
|
expect(link.href).toEqual("/one/11");
|
||||||
}));
|
}));
|
||||||
|
|
||||||
it("should accept a single command", inject([Router], (router) => {
|
it("should accept a single command", inject([Router, LocationStrategy], (router, locationStrategy) => {
|
||||||
let link = new RouterLink(null, router);
|
let link = new RouterLink(null, router, locationStrategy);
|
||||||
link.routerLink = '/one/11';
|
link.routerLink = '/one/11';
|
||||||
expect(link.href).toEqual("/one/11");
|
expect(link.href).toEqual("/one/11");
|
||||||
}));
|
}));
|
||||||
|
@ -61,4 +62,4 @@ export function main() {
|
||||||
|
|
||||||
@Component({template: ''})
|
@Component({template: ''})
|
||||||
class RootCmp {
|
class RootCmp {
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue