web-dev-qa-db-fra.com

Activer/Désactiver les balises d'ancrage avec AngularJS

Comment activer/désactiver les balises d'ancrage à l'aide de l'approche directive? 

Exemple: 

  1. en cliquant sur le lien modifier, créer et supprimer doit être désactivé ou grisé
  2. en cliquant sur le lien créer, l’édition et la suppression doivent être désactivées ou grisées

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);
                        }
                    });
                }
            }
       };
    }); 

LIEN CODE

52
John Smith

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:

  1. href liens à ne pas suivre lorsqu'on clique dessus
  2. ngClick événements à ne pas déclencher lorsque vous cliquez dessus
  3. styles modifiés en ajoutant une classe disabled

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;
}

Et voici le code en action, avec votre exemple

54
Wasmoo

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>
23
z0r

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>
9
Capt. Rochefort

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.

6
jsruok

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>
4
Julien

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.

Plunker simple pour démontrer le point

3
iiminov

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";
1
Rohan Gada

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>
1
Nitin...

Vous pouvez créer une directive personnalisée similaire à ng-disabled et désactiver un ensemble d'éléments spécifique en:

  1. surveiller les modifications de propriétés de la directive personnalisée, par exemple my-disabled.
  2. cloner l'élément actuel sans les gestionnaires d'événements ajoutés.
  3. ajoutez des propriétés css à l'élément cloné et à d'autres attributs ou gestionnaires d'événements qui fourniront l'état désactivé d'un élément.
  4. lorsque des modifications sont détectées sur la propriété surveillée, remplacez l'élément actuel par l'élément cloné.

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;
        }

      })
    }
  }
});
1
ryeballar

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

0
haimlit

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>

0
delta711