Reputation: 1105
How do I enable/disable anchor tags using the directive approach?
Example:
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);
}
});
}
}
};
});
Upvotes: 55
Views: 132518
Reputation: 199
ui-router v1.0.18
introduces support for ng-disabled
on anchor tags
Example: <a ui-sref="go" ng-disabled="true">nogo</a>
Upvotes: 0
Reputation: 545
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.
Upvotes: 6
Reputation: 726
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>
Upvotes: 10
Reputation: 8585
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>
Upvotes: 24
Reputation: 1324
You may, redefine the a
tag using angular directive:
angular.module('myApp').directive('a', function() {
return {
restrict: 'E',
link: function(scope, elem, attrs) {
if ('disabled' in attrs) {
elem.on('click', function(e) {
e.preventDefault(); // prevent link click
});
}
}
};
});
In html:
<a href="nextPage" disabled>Next</a>
Upvotes: 1
Reputation: 80
Make a toggle function in the respective scope to grey out the link.
First,create the following CSS classes in your .css file.
.disabled {
pointer-events: none;
cursor: default;
}
.enabled {
pointer-events: visible;
cursor: auto;
}
Add a $scope.state and $scope.toggle variable. Edit your controller in the JS file like:
$scope.state='on';
$scope.toggle='enabled';
$scope.changeState = function () {
$scope.state = $scope.state === 'on' ? 'off' : 'on';
$scope.toggleEdit();
};
$scope.toggleEdit = function () {
if ($scope.state === 'on')
$scope.toggle = 'enabled';
else
$scope.toggle = 'disabled';
};
Now,in the HTML a tags edit as:
<a href="#" ng-click="create()" class="{{toggle}}">CREATE</a><br/>
<a href="#" ng-click="edit()" class="{{toggle}}">EDIT</a><br/>
<a href="#" ng-click="delete()" class="{{toggle}}">DELETE</a>
To avoid the problem of the link disabling itself, change the DOM CSS class at the end of the function.
document.getElementById("create").className = "enabled";
Upvotes: 1
Reputation: 979
Have you tried using lazy evaluation of expressions like disabled || someAction()
?
Lets assume I defined something like so in my controller:
$scope.disabled = true;
Then I can disabling a link and apply inline styles like so:
<a data-ng-click="disabled || (GoTo('#/employer/'))" data-ng-style="disabled && { 'background-color': 'rgba(99, 99, 99, 0.5)', }">Higher Level</a>
Or better still disable a link and apply a class like so:
<a data-ng-click="disabled || (GoTo('#/employer/'))" data-ng-class="{ disabled: disabled }">Higher Level</a>
Note: that you will have a class="disabled"
applied to DOM element by that statement.
At this stage you just need to handle what you action GoTo()
will do. In my case its as simple as redirect to associated state:
$scope.GoTo = function (state) {
if (state != undefined && state.length > 0) {
$window.location.hash = state;
}
};
Rather than being limited by ngDisabled
you are limited by what you decide to do.
With this technique I successfully applied permission level checking to enable or disable user access to certain part of my module.
Simple plunker to demonstrate the point
Upvotes: 4
Reputation: 2246
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>
Upvotes: 4
Reputation: 1140
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 clickedngClick
events not to fire when clickeddisabled
classThis 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
Upvotes: 58
Reputation: 30098
You can create a custom directive that is somehow similar to ng-disabled and disable a specific set of elements by:
my-disabled
.HTML
<a my-disabled="disableCreate" href="#" ng-click="disableEdit = true">CREATE</a><br/>
<a my-disabled="disableEdit" href="#" ng-click="disableCreate = true">EDIT</a><br/>
<a my-disabled="disableCreate || disableEdit" href="#">DELETE</a><br/>
<a href="#" ng-click="disableEdit = false; disableCreate = false;">RESET</a>
JAVASCRIPT
directive('myDisabled', function() {
return {
link: function(scope, elem, attr) {
var color = elem.css('color'),
textDecoration = elem.css('text-decoration'),
cursor = elem.css('cursor'),
// double negation for non-boolean attributes e.g. undefined
currentValue = !!scope.$eval(attr.myDisabled),
current = elem[0],
next = elem[0].cloneNode(true);
var nextElem = angular.element(next);
nextElem.on('click', function(e) {
e.preventDefault();
e.stopPropagation();
});
nextElem.css('color', 'gray');
nextElem.css('text-decoration', 'line-through');
nextElem.css('cursor', 'not-allowed');
nextElem.attr('tabindex', -1);
scope.$watch(attr.myDisabled, function(value) {
// double negation for non-boolean attributes e.g. undefined
value = !!value;
if(currentValue != value) {
currentValue = value;
current.parentNode.replaceChild(next, current);
var temp = current;
current = next;
next = temp;
}
})
}
}
});
Upvotes: 1
Reputation: 2582
I'd expect anchor tags to lead to a static page with a url. I think that a buttons suits more to your use case, and then you can use ngDisabled to disable it. From the docs: https://docs.angularjs.org/api/ng/directive/ngDisabled
Upvotes: 0