Comment activer/désactiver les balises d'ancrage à l'aide de l'approche directive?
Exemple:
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);
}
});
}
}
};
});
Update: Désactiver le href fonctionne mieux dans le retour de la fonction de lien Le code ci-dessous a été mis à jour.
aDisabled
s'exécute naturellement avant ngClick
car les directives sont triées par ordre alphabétique. Lorsque aDisabled
est renommé en tagDisabled
, la directive fonctionne non.
Pour "désactiver" le "a" tag, je voudrais les choses suivantes:
href
liens à ne pas suivre lorsqu'on clique dessusngClick
événements à ne pas déclencher lorsque vous cliquez dessusdisabled
Cette directive le fait en imitant la directive ngDisabled. En fonction de la valeur de la directive a-disabled
, toutes les fonctionnalités ci-dessus sont basculées.
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();
}
});
};
}
};
});
Voici un style CSS qui pourrait indiquer une balise désactivée:
a.disabled {
color: #AAAAAA;
cursor: default;
pointer-events: none;
text-decoration: none;
}
Mon problème était légèrement différent: j'ai des balises d'ancrage qui définissent une href
, et je veux utiliser ng-disabled
pour empêcher le lien d'aller n'importe où lorsque vous cliquez dessus. La solution consiste à désélectionner la href
lorsque le lien est désactivé, comme ceci:
<a ng-href="{{isDisabled ? '' : '#/foo'}}"
ng-disabled="isDisabled">Foo</a>
Dans ce cas, ng-disabled
n'est utilisé que pour styliser l'élément.
Si vous voulez éviter en utilisant des attributs non officiels , vous devrez le nommer vous-même:
<style>
a.disabled {
color: #888;
}
</style>
<a ng-href="{{isDisabled ? '' : '#/foo'}}"
ng-class="{disabled: isDisabled}">Foo</a>
Pour les personnes ne voulant pas d'une réponse compliquée, j'ai utilisé Ng-If pour résoudre ce problème de manière similaire:
<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>
Modification de @ - Nitin's answer pour utiliser la désactivation dynamique:
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
}
});
}
};
});
Ceci vérifie l'existence de l'attribut désactivé et sa valeur à chaque clic.
Avertissement:
Le PO a fait ce commentaire sur une autre réponse:
Nous pouvons avoir ngDisabled pour les boutons ou les balises d’entrée; en utilisant CSS, nous pouvons faites en sorte que le bouton ressemble à une balise d'ancrage, mais cela n'aide pas beaucoup! JE était plus désireux de voir comment cela pouvait être fait en utilisant une approche directive ou façon angulaire de le faire?
Vous pouvez utiliser une variable à l'intérieur de l'étendue de votre contrôleur pour désactiver les liens/boutons en fonction du dernier bouton/lien sur lequel vous avez cliqué en utilisant ng-click
pour définir la variable à la valeur correcte et ng-disabled
pour désactiver le bouton lorsque cela est nécessaire à la valeur dans la variable.
J'ai mis à jour votre Plunker pour vous donner une idée.
Mais au fond, ça ressemble à ça:
<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>
Avez-vous essayé d’utiliser une évaluation paresseuse d’expressions telles que disabled || someAction()
?
Supposons que j'ai défini quelque chose comme ceci dans mon contrôleur:
$scope.disabled = true;
Ensuite, je peux désactiver un lien et appliquer des styles inline comme ceci:
<a data-ng-click="disabled || (GoTo('#/employer/'))" data-ng-style="disabled && { 'background-color': 'rgba(99, 99, 99, 0.5)', }">Higher Level</a>
Ou mieux encore, désactivez un lien et appliquez une classe comme ceci:
<a data-ng-click="disabled || (GoTo('#/employer/'))" data-ng-class="{ disabled: disabled }">Higher Level</a>
Remarque: vous aurez un class="disabled"
appliqué à l'élément DOM par cette instruction.
A ce stade, vous devez juste gérer ce que vous ferez de l'action GoTo()
. Dans mon cas, c'est aussi simple qu'une redirection vers un état associé:
$scope.GoTo = function (state) {
if (state != undefined && state.length > 0) {
$window.location.hash = state;
}
};
Plutôt que d’être limité par ngDisabled
, vous êtes limité par ce que vous décidez de faire.
Avec cette technique, j'ai appliqué avec succès la vérification du niveau d'autorisation pour activer ou désactiver l'accès des utilisateurs à certaines parties de mon module.
Créez une fonction bascule dans la portée respective en grisé le lien .
Commencez par créer les classes CSS suivantes dans votre fichier .css.
.disabled {
pointer-events: none;
cursor: default;
}
.enabled {
pointer-events: visible;
cursor: auto;
}
Ajoutez une variable $ scope.state et $ scope.toggle. Editez votre contrôleur dans le fichier JS comme suit:
$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';
};
Maintenant, dans le HTML, les balises sont éditées comme:
<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>
Pour éviter le problème du lien qui se désactive lui-même, Change la classe DOM CSS à la fin de la fonction.
document.getElementById("create").className = "enabled";
Vous pouvez, redéfinir la balise a
en utilisant la directive angulaire:
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
});
}
}
};
});
En html:
<a href="nextPage" disabled>Next</a>
Vous pouvez créer une directive personnalisée similaire à ng-disabled et désactiver un ensemble d'éléments spécifique en:
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;
}
})
}
}
});
Je m'attendrais à ce que les balises d'ancrage mènent à une page statique avec une URL. Je pense que les boutons conviennent mieux à votre cas d'utilisation, et vous pouvez ensuite utiliser ngDisabled pour le désactiver. Parmi les documents: https://docs.angularjs.org/api/ng/directive/ngDisabled
ui-router v1.0.18
introduit la prise en charge de ng-disabled
sur les balises d'ancrage
Exemple: <a ui-sref="go" ng-disabled="true">nogo</a>