5

I have a number of link in an Angular project (using Angular 2), similar to:

<a [routerLink]="..."
     [routerLinkActive]="..."
     [routerLinkActiveOptions]="...">
    Link
</a>

I would like to disable some of these depending on the context/state (by changing the color and preventing the action from happening).


For styling, I have added to the link:

[class.disabled]="!isValidLink()"

This lets me show the links as disabled, but I still need to prevent the routing. If I add a target="_self" to the element, it prevents routing, but I need to do this conditionally, depending on some state.

Is there any supported routing way of doing this, or some other implementation that would work?


Edit: Setting pointer-events to none in css would prevent clicking on the link, but am looking for a solution which would prevent keyboard events from triggering it too.

Yasir
  • 2,312
  • 4
  • 23
  • 35
  • 1
    Possible duplicate of [Angular 2, disable routerLink](http://stackoverflow.com/questions/35431188/angular-2-disable-routerlink) – elvin May 01 '17 at 15:59
  • Thanks, I am having the same issue; wondering if there is a way to prevent keyboard events too? That question has accepted an event which disables pointer-events, but tab-entering still triggers the link - would prefer this to not happen. – Yasir May 01 '17 at 16:07

4 Answers4

19

Another way to disable routerLink - replace onClick method.

To do this you have to create directive:

import { Directive, Input, Optional } from '@angular/core';
import { RouterLink, RouterLinkWithHref } from '@angular/router';

@Directive({
    selector: '[routerLink][disableLink]'
})
export class DisableLinkDirective {

    @Input() disableLink: boolean;

    constructor(
        // Inject routerLink
        @Optional() routerLink: RouterLink,
        @Optional() routerLinkWithHref: RouterLinkWithHref
    ) {

        const link =  routerLink || routerLinkWithHref;

        // Save original method
        const onClick = link.onClick;

        // Replace method
        link.onClick = (...args) => {
            if (this.disableLink) {
                return routerLinkWithHref? false: true;
            } else {
                return onClick.apply(link, args);
            }
        };
    }

}

Usage:

<a routerLink="/search" [disableLink]="!isLogged">Search</a>
taras-d
  • 1,789
  • 1
  • 12
  • 29
  • 4
    Searched far and wide for a solution that isn't a workaround but actually deactivates the routerLink conditionally. This is it. Works beautifully, and very simple to use. – Mvin May 17 '19 at 08:34
  • 2
    Still works in Angular 9. This should already be a default attribute for the router. Also, this thould be the accepted answer imo. – Stefan Falk Apr 19 '20 at 09:30
  • @MartinSchneider try to use tabindex="-1" for disabled links – taras-d Oct 26 '20 at 10:20
  • Very handy solution for scenarios when you only want expansion(not navigation) by clicking parent menu, and still using benefits of routerLinkActive. Thanks buddy – Efe Apr 09 '21 at 11:14
2

Give it a try like this:

<a [routerLink]="..."
    [class.disabled]="!isValidLink()" 
    (keydown.enter)="isValidLink()">Link</a>    
Yasir
  • 2,312
  • 4
  • 23
  • 35
elvin
  • 961
  • 1
  • 9
  • 26
  • +1 This does prevent the routing on keyboard enter key press, in addition to the styling and mouse event prevention through css. – Yasir May 01 '17 at 16:38
  • Yeah, it's not well documented in the [oficial site](https://angular.io/docs/ts/latest/guide/user-input.html), but here's a [post](https://www.bennadel.com/blog/3088-native-key-combination-event-binding-support-in-angular-2-beta-17.htm) about it – elvin May 01 '17 at 16:41
1

Could you do two anchor tags?

<a *ngIf="onCase" [routerLink]="..."
     [routerLinkActive]="..."
     [routerLinkActiveOptions]="...">
    Link
</a>
<a *ngIf="offcase" [class.disabled]="!isValidLink()">
    Link
</a>
DeborahK
  • 57,520
  • 12
  • 104
  • 129
  • Thanks, this would indeed work. I am wondering if there is a way of doing it in the existing element, so I don't need to maintain two elements for every link? – Yasir May 01 '17 at 16:09
  • Then check out the link that elvin posted for you. – DeborahK May 01 '17 at 16:11
  • It is a potentially workable solution, but would like to prevent keyboard events in addition to mouse events if possible. – Yasir May 01 '17 at 16:12
-2

See this. It uses a span element to capture click event and "preventDefault" with stopPropagation on span.
... It Works fine!

<a routerLink="/test"><span (click)="testClick($event)">Test link</span></a>
function testClick($event: MouseEvent) {
    if (expression) {
        $event.stopPropagation();
        // do something
        return;
    }
    // navigates to /test
}
Mattew Eon
  • 1,722
  • 1
  • 21
  • 38
  • If you are doing this that way you can probably still acticvate the link with the keyboard shortcuts. Also please show a quick code example it can help the user understand better what you are saying. – Mattew Eon Apr 18 '21 at 09:50