How can I conditionally disable the routerLink attribute?

AngularAngular2 Routing

Angular Problem Overview


In my Angular 2 application I'm trying to disable a routerLink without any success. I've tried to handle the click event on the click event (with event.preventDefault() and event.stopPropagation()) but it doesn't work.

How can I disable a routerLink?

Angular Solutions


Solution 1 - Angular

Disable pointer-events on the element via CSS:

<a [routerlink]="xxx" [class.disabled]="disabled ? true : null">Link</a>

a.disabled {
   pointer-events: none;
   cursor: default;
}

See also https://stackoverflow.com/questions/36985112/angular2-what-is-the-correct-way-to-disable-an-anchor-element

or

<a *ngIf="isEnabled" [routerlink]="xxx">Link</a>
<div *ngIf="!isEnabled">not a link</div>

or to easily reuse the disabled link template

<ng-template #disabledLink>
  <div *ngIf="!isEnabled">not a link</div>
</ng-template>
<a *ngIf="isEnabled; else disabledLink" [routerLink]="xxx">Link</a>

Solution 2 - Angular

Angular 13 and above

[routerLink]="null" (and undefined) is now officially used to disable the routerLink.
(see Docs)

So this is enough:

<a [routerLink]="linkEnabled ? 'path' : null">Link</a>

Angular 12 and below

[routerLink]="null" (and undefined) is treated as a shorthand for an empty array of commands. So it makes the routerLink to link to the current/active route. This behavior allows us to abuse the routerLinkActive directive for our purpose:

Template:

<a [routerLink]="linkEnabled ? 'path' : null"
   [routerLinkActive]="linkEnabled ? 'is_active' : 'is_disabled'">Link</a>

Optional CSS:

.is_disabled {
    cursor: default;
    text-decoration: none;
}

.is_active {
    // your style for active router link
}

Live demo (Angular 10):
See demo on StackBlitz

Detailed Description:

When linkEnabled returns false, null will make routerLink to link to the current/active route.

If routerLink links to the active route, the class which is specified in routerLinkActive will be applied. That will be is_disabled in this case.

There we can specify, how the disabled routerLink should appear.

routerLink to the active route won't trigger a navigation event.

Solution 3 - Angular

I've just had some success with a similar issue: having an array of nav links in an ngFor, some required [routerLink], while others required (click) - my issue was that all links relied on [routerLink] for [routerLinkActive], so I had to stop routerLink, without touching it's value.

`<a [routerLink]="item.link" routerLinkActive="isActive">
    <span (click)="item.click ? item.click($event) : void>
</a>`

with:

`click: ($event) => {
    $event.stopPropagation(); // Only seems to
    $event.preventDefault(); // work with both
    // Custom onClick logic
}`

As the span is inside, you can be sure the cancelling of the event happens before it bubbles up to [routerLink], while routerLinkActive will still apply.

Solution 4 - Angular

Disabling pointer-events on any html tag:

<div [routerLink]="['/home', { foo: bar }]"
     [ngStyle]="{'pointer-events': myLinkEnabled ? 'none' : null}">
     Click me
</div>

'none' resolves to disabling pointer-events, that is, disabling the link.

null resolves to ignore the style.

Solution 5 - Angular

Unfortunately, Angular doesn't seem to have a null value support for the routerLink.

However, this works for me. An example of my menu implementation:

<div *ngFor="let category of categories" [routerLink]="category.subcategories ? [] : [category.link]" (click)="toggleSubcategories(category)">

Simply put, if a category has any subcategories, don't redirect, but open the subcategories.

Solution 6 - Angular

All the top answer are workaround.

The best way is something you can find in this solution https://stackoverflow.com/a/45323200/3241192 by @taras-d

> 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>

Solution 7 - Angular

Try this:

<div *ngFor="let childitem of menuitem.MenuRoutes">
<a [routerLink]="menuitem.IsMain ? [childitem.Route] : []"><a>
</>

Solution 8 - Angular

My case was to use routerLink, sometimes use click to open modal, and internal logic of route URL if we don't provide routerLink URL. So for click, I had to delete routerLink.

[routerLink]="disableRouterLink ? null : (btnRouterLink || pathCondition)"

in my case, null deletes routerLink attribute, and I can use (click) event properly.

P.S. empty array [] provided in answers abowe doesn't remove attribute routerlink from the element.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTizianoLView Question on Stackoverflow
Solution 1 - AngularGünter ZöchbauerView Answer on Stackoverflow
Solution 2 - AngularMartin SchneiderView Answer on Stackoverflow
Solution 3 - AngularMike Muniom McBriarView Answer on Stackoverflow
Solution 4 - AngularJorgeView Answer on Stackoverflow
Solution 5 - AngularTomas LukacView Answer on Stackoverflow
Solution 6 - AngularCrocsxView Answer on Stackoverflow
Solution 7 - AngularErickView Answer on Stackoverflow
Solution 8 - AngularKurkov IgorView Answer on Stackoverflow