Enable/Disable Anchor Tags using AngularJS
Solution 1
Update: Disabling the href works better in the link function return. Code below has been updated.
aDisabled
naturally executes before ngClick
because directives are sorted in alphabetical order. When aDisabled
is renamed to tagDisabled
, the directive does not work.
To "disable" the "a" tag, I'd want the following things:
-
href
links not to be followed when clicked -
ngClick
events not to fire when clicked - styles changed by adding a
disabled
class
This directive does this by mimicking the ngDisabled directive. Based on the value of a-disabled
directive, all of the above features are toggled.
myApp.directive('aDisabled', function() {
return {
compile: function(tElement, tAttrs, transclude) {
//Disable ngClick
tAttrs["ngClick"] = "!("+tAttrs["aDisabled"]+") && ("+tAttrs["ngClick"]+")";
//return a link function
return function (scope, iElement, iAttrs) {
//Toggle "disabled" to class when aDisabled becomes true
scope.$watch(iAttrs["aDisabled"], function(newValue) {
if (newValue !== undefined) {
iElement.toggleClass("disabled", newValue);
}
});
//Disable href on click
iElement.on("click", function(e) {
if (scope.$eval(iAttrs["aDisabled"])) {
e.preventDefault();
}
});
};
}
};
});
Here is a css style that might indicate a disabled tag:
a.disabled {
color: #AAAAAA;
cursor: default;
pointer-events: none;
text-decoration: none;
}
And here is the code in action, with your example
Solution 2
My problem was slightly different: I have anchor tags that define an href
, and I want to use ng-disabled
to prevent the link from going anywhere when clicked. The solution is to un-set the href
when the link is disabled, like this:
<a ng-href="{{isDisabled ? '' : '#/foo'}}"
ng-disabled="isDisabled">Foo</a>
In this case, ng-disabled
is only used for styling the element.
If you want to avoid using unofficial attributes, you'll need to style it yourself:
<style>
a.disabled {
color: #888;
}
</style>
<a ng-href="{{isDisabled ? '' : '#/foo'}}"
ng-class="{disabled: isDisabled}">Foo</a>
Solution 3
For people not wanting a complicated answer, I used Ng-If to solve this for something similar:
<div style="text-align: center;">
<a ng-if="ctrl.something != null" href="#" ng-click="ctrl.anchorClicked();">I'm An Anchor</a>
<span ng-if="ctrl.something == null">I'm just text</span>
</div>
Solution 4
Modifying @Nitin's answer to work with dynamic disabling:
angular.module('myApp').directive('a', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
elem.on('click', function(e) {
if (attrs.disabled) {
e.preventDefault(); // prevent link click
}
});
}
};
});
This checks the existence of disabled attribute and its value upon every click.
Solution 5
Disclaimer:
The OP has made this comment on another answer:
We can have ngDisabled for buttons or input tags; by using CSS we can make the button to look like anchor tag but that doesn't help much! I was more keen on looking how it can be done using directive approach or angular way of doing it?
You can use a variable inside the scope of your controller to disable the links/buttons according to the last button/link that you've clicked on by using ng-click
to set the variable at the correct value and ng-disabled
to disable the button when needed according to the value in the variable.
I've updated your Plunker to give you an idea.
But basically, it's something like this:
<div>
<button ng-click="create()" ng-disabled="state === 'edit'">CREATE</button><br/>
<button ng-click="edit()" ng-disabled="state === 'create'">EDIT</button><br/>
<button href="" ng-click="delete()" ng-disabled="state === 'create' || state === 'edit'">DELETE</button>
</div>
John Smith
Updated on July 09, 2022Comments
-
John Smith almost 2 years
How do I enable/disable anchor tags using the directive approach?
Example:
- while clicking on edit link, create & delete needs to be disabled or grayed out
- while clicking on create link, edit & delete needs to be disabled or grayed out
JAVASCRIPT:
angular.module('ngApp', []).controller('ngCtrl',['$scope', function($scope){ $scope.create = function(){ console.log("inside create"); }; $scope.edit = function(){ console.log("inside edit"); }; $scope.delete = function(){ console.log("inside delete"); }; }]).directive('a', function() { return { restrict: 'E', link: function(scope, elem, attrs) { if(attrs.ngClick || attrs.href === '' || attrs.href === '#'){ elem.on('click', function(e){ e.preventDefault(); if(attrs.ngClick){ scope.$eval(attrs.ngClick); } }); } } }; });
-
John Smith about 10 yearsWe can have ngDisabled for buttons or input tags; by using CSS we can make the button to look like anchor tag but that doesn't help much! I was more keen on looking how it can be done using directive approach or angular way of doing it?
-
ryeballar about 10 yearsThe title suggests an anchor tag, not a button.
-
Julien about 10 years@ryeballar Did you read the comment made by the OP on the other answer ?
-
Wasmoo over 9 yearsIt prevents
ng-click
from firing whena-disabled
is false. It does this by changing the function before it gets processed, effectively turning<a ng-click="doSomething()" a-disabled="isDisabled()">
into<a ng-click="!isDisabled() && doSomething()">
-
Kenneth Sundqvist over 9 yearsYes, I understand that line as a whole. But I'm specifically wondering about the part that I isolated in my comment.
(a, b)
will execute both expressiona
andb
but only return the value ofb
. In this case expressiona
is a string, so my understanding is that it's redundant. I left it out when I used this directive and it's still working as expected. -
Wasmoo over 9 yearsI must have grabbed that bit of code from something else and let it go because I didn't understand the Javascript Comma Operator. I agree, it can safely be removed.
-
Marwen Trabelsi about 9 years@Julien : you have to mention in the top of your response that you answered the comment rather than the original question.
-
Julien about 9 years@SmartyTwiti Done. Could you remove your downvote now?
-
Shannon Hochkins almost 9 yearsFor those who might want to perform a different task if it's disabled, simply add this
if (angular.isDefined(iAttrs["aOnDisabledClick"])) scope.$eval(iAttrs["aOnDisabledClick"]);
beforee.preventDefault()
and then add thea-on-disabled-click
attribute to your anchor and parse it a function in that scope. -
DrB over 8 yearsNg-diabled won't work for tag a as the tag itself does not accept such attribute.
-
z0r over 8 years@BehnazChangizi It works, but may not be future-proof. I added an example that uses a class instead.
-
jemiloii about 8 yearsThis is completely future proof, all he is doing is creating an empty href if the link is disabled.
-
Coderer over 7 yearsIt's a pretty bad habit to put navigation in a click event -- you can't (for example) open a page in a new tab/window if you don't express links as, well, links.
-
iiminov over 7 years@Coderer Perhaps you would like to add an example demonstrating a better way to handle this usecase?
-
Coderer over 7 yearsThe two highest rated answers already use
href
manipulation instead of click events. And I should clarify: if you want a "do something" button, click events are fine, but use a<button>
. If you want a "go somewhere" link, use<a href=...>
but make thehref
meaningful. -
iiminov over 7 years@Coderer I totally agree with you. But you have to take into account the way the original question is phrased
How do I enable/disable anchor tags
. I provided another possibility of how I enable/disable clicks on a<div>
tag when a condition is met. And in my case, I had to use a<div>
tag because of dependency on third party module. It is fair to point that this approach is not the best if you need to navigate somewhere but as demonstrated there is nothing stopping you from doing so. -
Isaac Gregson over 7 yearsNote that
pointer-events: none;
disables the event from firing. Thus, in such cases, there's no need to disable it via JS (e.preventDefault();
). Browser support is good (caniuse.com/#feat=pointer-events). -
Isaac Gregson over 7 yearsAlso, to prevent increased CSS specificity, I prefer to simply use
[disabled] { pointer-events: none; }...
-
Shadow The Kid Wizard over 7 yearsYeah, that's what I'm doing myself. Not very elegant but simple and useful. :)
-
Pierre Chavaroche about 7 yearsGood idea! And I think
if (attrs.disabled)
should be enough. -
Felipe Leão about 7 yearsYou should invert the order between the check on
disabled
and theelem.on('click')
redefinition. -
Nitin... about 7 yearsFewer events, better performance, disabled anchors will always be a subset on all anchors
-
Salman Lone almost 7 yearswhat if someone wants to show the <a> tag but disabled.