This is an improved version of the original answer by @taras-d.
Credit goes to the original author.
Create one Directive
import { Directive, Host, Input, isDevMode, Optional } from '@angular/core';
import { RouterLink, RouterLinkWithHref } from '@angular/router';
/**
* @ngModule RouterModule
*
* @description
*
* A directive that prevents navigation when applied to elements with [routerLink] or [routerLinkWithHref].
* When the `suppressNavigation` input is `true`, the directive intercepts the default behavior of the link's click event.
* This allows the navigation to be suppressed, preventing the route change.
*
* @param suppressNavigation - A boolean that determines whether the navigation should be suppressed.
*
* @throws Error if used without [routerLink] or [routerLinkWithHref].
*
* @publicApi
* @see {@link RouterLink}
* @see {@link RouterLinkWithHref}
*
* @remarks
* Inspired by a [Stack Overflow answer by taras-d](https://stackoverflow.com/a/45323200/14344959).
* Credit goes to the original author.
*/
@Directive({
selector: '[suppressNavigation]',
standalone: true
})
export class SuppressNavigationDirective {
@Input() suppressNavigation: boolean = false;
constructor(
// Inject routerLink
@Optional() @Host() routerLink: RouterLink,
@Optional() @Host() routerLinkWithHref: RouterLinkWithHref
) {
const link = routerLink || routerLinkWithHref;
if (!link) {
if (isDevMode()) {
throw new Error(
'[suppressNavigation] directive must be used on an element with [routerLink] or [routerLinkWithHref].'
);
}
return; // Safety check
}
// Save original click handler
const originalOnClick = link.onClick;
// Override click handler
link.onClick = (...args) => {
if (this.suppressNavigation) {
return routerLinkWithHref ? false : true;
} else {
return originalOnClick.apply(link, args);
}
};
}
}
Usage:
<a routerLink="/search" [suppressNavigation]="!isLogged">Search</a>