Angular2, what is the correct way to disable an anchor element?


Angular2, what is the correct way to disable an anchor element?



I'm working on an Angular2 application, and I need to display -- but disable an <a> HTML element. What is the correct way to do this?


disable


<a>



Updated



Please note the *ngFor, this would prevent the option of using *ngIf and not rendering the <a> altogether.


*ngFor


*ngIf


<a>


<a *ngFor="let link of links"
href="#"
[class.disabled]="isDisabled(link)"
(click)="onClick(link)">
{{ link.name }}
</a>



The TypeScript component has a method that looks like this:


onClick(link: LinkObj) {
// Do something relevant with the object...
return false;
}



I need to actually prevent the element from being clickable, not just appear that it is with the CSS. I was assuming that I needed to potentially bind to the [disabled] attribute at first, but this is incorrect as the anchor element doesn't have a disabled property.


[disabled]


disabled



I looked at and considered using the pointer-events: none but this prevents my style of cursor: not-allowed from working -- and this is part of the requirement.


pointer-events: none


cursor: not-allowed




6 Answers
6



Specifying pointer-events: none in CSS disables mouse input but doesn't disable keyboard input. For example, the user can still tab to the link and "click" it by pressing the Enter key or (in Windows) the ≣ Menu key. You could disable specific keystrokes by intercepting the keydown event, but this would likely confuse users relying on assistive technologies.


pointer-events: none


keydown



Probably the best way to disable a link is to remove its href attribute, making it a non-link. You can do this dynamically with a conditional href attribute binding:


href


href


<a *ngFor="let link of links"
[attr.href]="isDisabled(link) ? null : '#'"
[class.disabled]="isDisabled(link)"
(click)="!isDisabled(link) && onClick(link)">
{{ link.name }}
</a>



Or, as in Günter Zöchbauer's answer, you can create two links, one normal and one disabled, and use *ngIf to show one or the other:


*ngIf


<ng-template ngFor #link [ngForOf]="links">
<a *ngIf="!isDisabled(link)" href="#" (click)="onClick(link)">{{ link.name }}</a>
<a *ngIf="isDisabled(link)" class="disabled">{{ link.name }}</a>
</ng-template>



Here's some CSS to make the link look disabled:


a.disabled {
color: gray;
cursor: not-allowed;
text-decoration: underline;
}





Even the the <a> element lacks an href it is still clickable, I just verified this...what now? Still not perfect.
– David Pine
May 3 '16 at 13:39


<a>


href





@DavidPine: I've updated my answer to handle the click event.
– Michael Liu
May 3 '16 at 15:02


click





Updated question
– David Pine
May 3 '16 at 15:56





@DavidPine: Last update, I hope! :-p
– Michael Liu
May 3 '16 at 15:58





LOL, me too - I wish this were simpler...
– David Pine
May 3 '16 at 16:08



For [routerLink] you can use:


[routerLink]



Adding this CSS should do what you want:


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



This should fix the issue mentioned by @MichelLiu in the comments:


<a href="#" [class.disabled]="isDisabled(link)"
(keydown.enter)="!isDisabled(link)">{{ link.name }}</a>



Another approach


<a [routerLink]="['Other']" *ngIf="!isDisabled(link)">{{ link.name }}</a>
<a *ngIf="isDisabled(link)">{{ link.name }}</a>



Plunker example





So I wouldn't want to bind to [disabled], why not?
– David Pine
May 2 '16 at 14:41


[disabled]





stackoverflow.com/questions/13955667/disabled-href-tag
– Günter Zöchbauer
May 2 '16 at 14:49





The user can still tab to the link and press Enter.
– Michael Liu
May 2 '16 at 15:56





@GünterZöchbauer Every Angular question I have searched for on SO, you have answered! Nice work!
– JMK
Nov 27 '17 at 21:07





@JMK thanks :D It was fun. Sadly not that much time anymore.
– Günter Zöchbauer
Nov 27 '17 at 21:20



Just came across this question, and wanted to suggest an alternate approach.



In the markup the OP provided, there is a click event binding. This makes me think that the elements are being used as "buttons". If that is the case, they could be marked up as <button> elements and styled like links, if that is the look you desire. (For example, Bootstrap has a built-in "link" button style, https://v4-alpha.getbootstrap.com/components/buttons/#examples)


<button>



This has several direct and indirect benefits. It allows you to bind to the disabled property, which when set will disable mouse and keyboard events automatically. It lets you style the disabled state based on the disabled attribute, so you don't have to also manipulate the element's class. It is also better for accessibility.


disabled



For a good write-up about when to use buttons and when to use links, see Links are not buttons. Neither are DIVs and SPANs


.disabled{ pointer-events: none }



will disable the click event, but not the tab event. To disable the tab event, you can set the tabindex to -1 if the disable flag is true.


<li [routerLinkActive]="['active']" [class.disabled]="isDisabled">
<a [routerLink]="['link']" tabindex="{{isDisabled?-1:0}}" > Menu Item</a>
</li>



My answer might be late for this post. It can be achieved through inline css within anchor tag only.



<a [routerLink]="['/user']" [style.pointer-events]="isDisabled ?'none':'auto'">click-label</a>


<a [routerLink]="['/user']" [style.pointer-events]="isDisabled ?'none':'auto'">click-label</a>



Considering isDisabled is a property in component which can be true or false.


isDisabled


true


false



Plunker for it:
https://embed.plnkr.co/TOh8LM/





I do not believe this is correct. Angular still propagates the (click) binding, as such it would still occur. Please create a plunker with this and share it here.
– David Pine
Jun 21 at 18:26





@DavidPine I add one plunker for it. embed.plnkr.co/TOh8LM I just gave reference for href tag in that, similarly it can work with routerLink directive within anchor tag
– vineetk27
Jul 1 at 14:18


routerLink



You can try this


<a [attr.disabled]="someCondition ? true: null"></a>






By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Popular posts from this blog

List of Kim Possible characters

Audio Livestreaming with Python & Flask

NSwag: Generate C# Client from multiple Versions of an API