LDB
LDB

Reputation: 611

Disable a link in angular 2+

I'm attempting to disable a link until an API call is made in Angular 6. I want the link to be disabled until the getSelectedDealer() API is returned.

 <menu-link *ngIf="perms.has(perms.TOP_OFFERS) && _dealerPersistenceService.getSelectedDealer()"
           route="/dynamic-journeys/{{getDealerId()}}/vehicles">
    <menu-item><img src="/assets/menu-icons/top-offers.svg">Dynamic Journeys</menu-item>
</menu-link>

Here is the code for the 'a' tag component and the CSS.

<a [routerLink]="route" routerLinkActive="active" class="menu-link" [class.disabled]="disabled ? true: null">
<ng-content select="menu-item"></ng-content>

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

Basically I need the 'menu-link' items to be disabled prior to API call and be enabled after.

Upvotes: 16

Views: 61378

Answers (4)

Vinoth
Vinoth

Reputation: 11

I think it's achievable as per your needs. Suppose you are using component you can create a service object. Use it in the component where you want to enable/disable a href. Otherwise as mentioned by above answers. If you want don't want to use prevent default you can simple return false.

    check($event){
     return false;
    }

Upvotes: 0

dAxx_
dAxx_

Reputation: 2290

If you want to use no matter what, you could achieve that by simply add click event to this link with something like that:

<a [routerLink]="route"
   routerLinkActive="active"
   class="menu-link"
   [class.disabled]="disabled ? true: null"
   (click)="check($event)">

In TS:

isReady = false;
check = (event) => {
 if (!this.isReady) {
   event.preventDefault();
 }
}

So isReady is a boolean variable of your component, and it is false until you want to. When ever you click this link, it will check if it is true, but if it is false, it will prevent the original behavior of the event, and nothing will fire.

Upvotes: 11

Rusty Rob
Rusty Rob

Reputation: 17173

Angular needs a way to selectively apply directives, but here was my solution:

<a
    (click)="markAsRead(notification);notification.externalUrl || $event.preventDefault()"
    [href]="notification.externalUrl"
    target="_blank""
...>

Upvotes: 6

Ashish Ranjan
Ashish Ranjan

Reputation: 12950

In your component have a flag which tells whether the API has returned..:

apiReturned = false;

ngOnInit() {

   setTimeout(() => {
      // simulating API call, sets to true after 5 seconds
      this.apiReturned = true;
   }, 5000);
}

And have your HTML like:

 <a [class.disabled]="apiReturned ? null: true"  [href]="apiReturned ? 'https://stackoverflow.com/users/9442497/ldb' : null" >Click Me!</a>

Here I have also removed the href from the anchor when it is supposed to be disabled.

EDIT

If your anchor tag resides in a different component, then you have two ways to perform the task.

  1. Send the Route and the API's status to the mat-link component and act accordingly
  2. Have a service which takes the value of API status from the parent component and use the service's data in mat-link component. I would prefer using a service because you will also have to block the route from the URL bar when the API has not returned, using Input you can only block the link, but that will not help if someone directly enters the route url in the URL bar. You can use Angular's Route Guard to prevent routing in such cases

I will explain the usage of the first way and leave the second way for you to implement.

In your mat-link component.ts, have something like:

export class MatLinkComponent  {
  @Input() route: string;
  @Input() apiReturned: boolean;
}

And in your mat-link.component.html, have something like:

<a *ngIf="!apiReturned" href="#" [class.disabled]="!apiReturned" >Click Me!</a>

<a *ngIf="apiReturned" [routerLink]="route" routerLinkActive="active" >Click Me!</a>

You could notice that I have created two anchor tags which are conditional, this is because, routerlink won't accept null and we don't have something like conditional routerLink yet.

In the parent component, say app.component.html or wherever you are using mat-link.component, have something like:

<mat-link 
      [apiReturned]=apiReturned
      [route]="'routinghere'">
</mat-link>

You can See a working example here: Example. The Click Me! link will activate after 10 seconds..

Upvotes: 4

Related Questions