How can I conditionally disable the routerLink attribute?
AngularAngular2 RoutingAngular 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;
}
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.