Tadeu Bento

Angular: RouterLink Ctrl+Click New Tab

In Angular projects, it’s common to use [routerLink] in template elements to handle navigation. While effective, this approach lacks the functionality of “Ctrl + Click” (or “Cmd + Click” on macOS) to open links in a new browser tab. In this post, I’ll share a simple yet effective directive to implement this feature.

Before you jump to the code, please note that this solution may not be what you’re looking for. If you’re dealing with <a> tags then the default [routerLink] is able to handle “Ctrl + Click” and open your content in a new tab. This directive is intended to be used in buttons, table rows, divs and other elements.

import {Directive, HostListener, Input} from '@angular/core';
import {Router, UrlSerializer} from '@angular/router';

@Directive({
  selector: '[ctrlRouterLink]'
})
export class CtrlRouterLinkDirective {

  @Input('ctrlRouterLink') routerLinkParts: string[] = [];

  constructor(
    private router: Router,
    private urlSerializer: UrlSerializer
  ) {
  }

  @HostListener('click', ['$event'])
  handleClick(event: MouseEvent): void {
    this.navigate(event.ctrlKey, this.routerLinkParts);
  }

  navigate(inNewWindow = false, routerLinkParts: string[], routerLinkFragment?: string): void {
    if (inNewWindow) {
      const tree = this.router.createUrlTree(routerLinkParts);
      let fullUrl = this.urlSerializer.serialize(tree);
      if (routerLinkFragment) {
        fullUrl += '#' + routerLinkFragment;
      }
      window.open(fullUrl, '_blank');
      return;
    }
    this.router.navigate(routerLinkParts, { fragment: routerLinkFragment });
  }

}

The directive can be used in your templates as a simple drop-in replacement for traditional [routerLink]:

<tr *ngFor="let item of items" [ctrlRouterLink]="['/', 'target', single.id]">

It may also be injected into a component and called if required. This is useful when more complex for URL generation is required:

constructor(
    private ctrlRouterLinkDirective: CtrlRouterLinkDirective
(...)

someEvent($event, item) {
    (...)
    this.ctrlRouterLinkDirective.navigate($event.ctrlKey, ['/', 'target', item.id],
}

That’s it!

Exit mobile version