web-dev-qa-db-fra.com

Quelle est la meilleure façon d'appliquer conditionnellement une classe?

Disons que vous avez un tableau rendu dans un ul avec un li pour chaque élément et une propriété du contrôleur appelée selectedIndex. Quelle serait la meilleure façon d’ajouter une classe à li avec l’index selectedIndex dans AngularJS?

Je duplique actuellement (à la main) le code li et l'ajoute à l'une des balises li et j'utilise ng-show et ng-hide pour afficher un seul li.

1166
respectTheCode

Si vous ne souhaitez pas mettre les noms de classe CSS dans Controller comme je le fais, voici un vieux truc que j'utilise depuis les jours précédents. Nous pouvons écrire une expression qui correspond directement à un nom de classe sélectionné, aucune directive personnalisée n'est nécessaire:

ng:class="{true:'selected', false:''}[$index==selectedIndex]"

Veuillez noter l'ancienne syntaxe avec deux points.

Il existe également une nouvelle meilleure façon d'appliquer des classes de manière conditionnelle, comme:

ng-class="{selected: $index==selectedIndex}"

Angular prend désormais en charge les expressions qui renvoient un objet. Chaque propriété (nom) de cet objet est maintenant considérée comme un nom de classe et est appliquée en fonction de sa valeur.

Cependant, ces moyens ne sont pas fonctionnellement égaux. Voici un exemple:

ng-class="{admin:'enabled', moderator:'disabled', '':'hidden'}[user.role]"

Nous pourrions donc réutiliser des classes CSS existantes en mappant fondamentalement une propriété de modèle à un nom de classe tout en maintenant les classes CSS en dehors du code du contrôleur.

1378
orcun

ng-class supporte une expression qui doit être évaluée à

  1. Une chaîne de noms de classes délimités par des espaces, ou
  2. Un tableau de noms de classe, ou
  3. Une carte/objet de noms de classe en valeurs booléennes.

Donc, en utilisant le formulaire 3), nous pouvons simplement écrire

ng-class="{'selected': $index==selectedIndex}"

Voir aussi Comment puis-je appliquer de manière conditionnelle des styles CSS dans AngularJS? pour une réponse plus large.


Mise à jour : Angular 1.1.5 prend en charge un opérateur ternaire , donc si cette construction est plus familier pour vous:

ng-class="($index==selectedIndex) ? 'selected' : ''"
434
Mark Rajcok

Ma méthode préférée utilise l'expression ternaire.

ng-class="condition ? 'trueClass' : 'falseClass'"

Note: Si vous utilisez une ancienne version de Angular, vous devriez utiliser ceci à la place,

ng-class="condition && 'trueClass' || 'falseClass'"
159
skmvasu

J'ajouterai à cela car certaines de ces réponses semblent périmées. Voici comment je le fais:

<class="ng-class:isSelected">

Où 'isSelected' est une variable javascript définie dans le contrôleur angular défini.


Pour répondre plus précisément à votre question, voici comment vous pouvez générer une liste avec celle-ci:

HTML

<div ng-controller="ListCtrl">  
    <li class="ng-class:item.isSelected" ng-repeat="item in list">   
       {{item.name}}
    </li>  
</div>


JS

function ListCtrl($scope) {    
    $scope.list = [  
        {"name": "Item 1", "isSelected": "active"},  
        {"name": "Item 2", "isSelected": ""}
    ]
}


Voir: http://jsfiddle.net/tTfWM/

Voir: http://docs.angularjs.org/api/ng.directive:ngClass

54
stefano

Voici une solution beaucoup plus simple:

function MyControl($scope){
    $scope.values = ["a","b","c","d","e","f"];
    $scope.selectedIndex = -1;
    
    $scope.toggleSelect = function(ind){
        if( ind === $scope.selectedIndex ){
            $scope.selectedIndex = -1;
        } else{
            $scope.selectedIndex = ind;
        }
    }
    
    $scope.getClass = function(ind){
        if( ind === $scope.selectedIndex ){
            return "selected";
        } else{
            return "";
        }
    }
       
    $scope.getButtonLabel = function(ind){
        if( ind === $scope.selectedIndex ){
            return "Deselect";
        } else{
            return "Select";
        }
    }
}
.selected {
    color:red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app ng-controller="MyControl">
    <ul>
        <li ng-class="getClass($index)" ng-repeat="value in values" >{{value}} <button ng-click="toggleSelect($index)">{{getButtonLabel($index)}}</button></li>
    </ul>
    <p>Selected: {{selectedIndex}}</p>
</div>
46
user81962

Récemment, j'ai rencontré un problème similaire et j'ai décidé de créer un filtre conditionnel:

  angular.module('myFilters', []).
    /**
     * "if" filter
     * Simple filter useful for conditionally applying CSS classes and decouple
     * view from controller 
     */
    filter('if', function() {
      return function(input, value) {
        if (typeof(input) === 'string') {
          input = [input, ''];
        }
        return value? input[0] : input[1];
      };
    });

Cela prend un seul argument, qui est soit un tableau à 2 éléments, soit une chaîne, qui devient un tableau auquel est ajoutée une chaîne vide en tant que second élément:

<li ng-repeat="item in products | filter:search | orderBy:orderProp |
  page:pageNum:pageLength" ng-class="'opened'|if:isOpen(item)">
  ...
</li>
26
Lèse majesté

Si vous voulez aller au-delà de l'évaluation binaire et garder votre CSS en dehors de votre contrôleur, vous pouvez implémenter un simple filtre qui évalue l'entrée par rapport à un objet de la carte:

angular.module('myApp.filters, [])
  .filter('switch', function () { 
      return function (input, map) {
          return map[input] || '';
      }; 
  });

Cela vous permet d'écrire votre balisage comme ceci:

<div ng-class="muppets.star|switch:{'Kermit':'green', 'Miss Piggy': 'pink', 'Animal': 'loud'}">
    ...
</div>
21
Joe Steele

L'été j'ai récemment fait qui faisait ceci:

<input type="password"  placeholder="Enter your password"
ng-class="{true: 'form-control isActive', false: 'isNotActive'}[isShowing]">

La valeur isShowing est une valeur qui se trouve sur mon contrôleur et que l'on clique en cliquant sur un bouton. Les parties entre les parenthèses simples sont des classes que j'ai créées dans mon fichier css.

EDIT: J'aimerais également ajouter que codeschool.com propose un cours gratuit parrainé par Google sur AngularJS, qui passe en revue tous ces éléments, et plus encore. Il n'y a pas besoin de payer pour quoi que ce soit, il suffit de créer un compte et de commencer! Bonne chance à tous!

17
Pytth

Opérateur ternaire vient d'être ajouté à angular analyseur dans 1.1.5 .

Donc, le moyen le plus simple de faire cela est maintenant:

ng:class="($index==selectedIndex)? 'selected' : ''"
15
lionroots

Nous pouvons créer une fonction pour gérer la classe de retour avec condition

enter image description here

<script>
    angular.module('myapp', [])
            .controller('ExampleController', ['$scope', function ($scope) {
                $scope.MyColors = ['It is Red', 'It is Yellow', 'It is Blue', 'It is Green', 'It is Gray'];
                $scope.getClass = function (strValue) {
                    switch(strValue) {
                        case "It is Red":return "Red";break;
                        case "It is Yellow":return "Yellow";break;
                        case "It is Blue":return "Blue";break;
                        case "It is Green":return "Green";break;
                        case "It is Gray":return "Gray";break;
                    }
                }
        }]);
</script>

Puis

<body ng-app="myapp" ng-controller="ExampleController">

<h2>AngularJS ng-class if example</h2>
<ul >
    <li ng-repeat="icolor in MyColors" >
        <p ng-class="[getClass(icolor), 'b']">{{icolor}}</p>
    </li>
</ul>
<hr/>
<p>Other way using : ng-class="{'class1' : expression1, 'class2' : expression2,'class3':expression2,...}"</p>
<ul>
    <li ng-repeat="icolor in MyColors">
        <p ng-class="{'Red':icolor=='It is Red','Yellow':icolor=='It is Yellow','Blue':icolor=='It is Blue','Green':icolor=='It is Green','Gray':icolor=='It is Gray'}" class="b">{{icolor}}</p>
    </li>
</ul>

Vous pouvez vous référer à la page de code complète à l’adresse exemple: ng-class

11
Lewis Hai

Ça fonctionne super bien ;)

<ul class="nav nav-pills" ng-init="selectedType = 'return'">
    <li role="presentation" ng-class="{'active':selectedType === 'return'}"
        ng-click="selectedType = 'return'"><a href="#return">return

    </a></li>
    <li role="presentation" ng-class="{'active':selectedType === 'oneway'}"
        ng-click="selectedType = 'oneway'"><a href="#oneway">oneway
    </a></li>
</ul>
9
Aliti

Je suis nouveau sur Angular mais j'ai trouvé ceci pour résoudre mon problème:

<i class="icon-download" ng-click="showDetails = ! showDetails" ng-class="{'icon-upload': showDetails}"></i>

Ceci appliquera de manière conditionnelle une classe basée sur un var. Il commence avec icon-download par défaut, using-ng-class, je vérifie l’état de showDetails si true/false et applique la classe icon- télécharger. Cela fonctionne très bien.

J'espère que ça aide.

9
Ravi Ram

Cela passera probablement pour l'oubli, mais voici comment j'ai utilisé les opérateurs ternaires de la 1.1.5 pour changer de classe selon que la ligne d'une table est la première, la seconde ou la dernière - sauf s'il n'y a qu'une seule ligne dans la table:

<span class="attribute-row" ng-class="(restaurant.Attributes.length === 1) || ($first ? 'attribute-first-row': false || $middle ? 'attribute-middle-row': false || $last ? 'attribute-last-row': false)">
</span>
5
sundar

Voici une autre option qui fonctionne bien lorsque ng-class ne peut pas être utilisé (par exemple lors du stylage SVG):

ng-attr-class="{{someBoolean && 'class-when-true' || 'class-when-false' }}"

(Je pense que vous devez être sur la dernière version instable Angular pour utiliser ng-attr-, je suis actuellement sur 1.1.4)

4
Ashley Davis

partiel

  <div class="col-md-4 text-right">
      <a ng-class="campaign_range === 'thismonth' ? 'btn btn-blue' :  'btn btn-link'" href="#" ng-click='change_range("thismonth")'>This Month</a>
      <a ng-class="campaign_range === 'all' ? 'btn btn-blue' :  'btn btn-link'" href="#" ng-click='change_range("all")'>All Time</a>
  </div>

manette

  $scope.campaign_range = "all";
  $scope.change_range = function(range) { 
        if (range === "all")
        {
            $scope.campaign_range = "all"
        }
        else
        {  
            $scope.campaign_range = "thismonth"
        }
  };
4
Caner Çakmak

eh bien, je vous suggère de vérifier la condition de votre contrôleur avec une fonction retournant true ou false.

<div class="week-wrap" ng-class="{today: getTodayForHighLight(todayDate, day.date)}">{{day.date}}</div>

et dans votre contrôleur vérifier l'état

$scope.getTodayForHighLight = function(today, date){
return (today == date);
}
4
sheelpriy

C'est dans mon travail multiple juger sous condition:

<li ng-repeat='eOption in exam.examOptions' ng-class="exam.examTitle.ANSWER_COM==exam.examTitle.RIGHT_ANSWER?(eOption.eoSequence==exam.examTitle.ANSWER_COM?'right':''):eOption.eoSequence==exam.examTitle.ANSWER_COM?'wrong':eOption.eoSequence==exam.examTitle.RIGHT_ANSWER?'right':''">
  <strong>{{eOption.eoSequence}}</strong> &nbsp;&nbsp;&nbsp;&nbsp;|&nbsp;&nbsp;&nbsp;&nbsp;
  <span ng-bind-html="eOption.eoName | to_trusted">2020 元</span>
</li>
4
H.jame

J'ajoute simplement quelque chose qui a fonctionné pour moi aujourd'hui, après de nombreuses recherches ...

<div class="form-group" ng-class="{true: 'has-error'}[ctrl.submitted && myForm.myField.$error.required]">

J'espère que cela vous aidera dans votre développement réussi.

=)

Syntaxe d'expression non documentée: Lien excellent vers un site Web ... =)

3
Robert Green MBA

Si vous avez une classe commune appliquée à de nombreux éléments, vous pouvez créer une directive personnalisée qui l'ajoutera comme ng-show/ng-hide.

Cette directive ajoutera la classe 'active' au bouton si on clique dessus

module.directive('ngActive',  ['$animate', function($animate) {
  return function(scope, element, attr) {
    scope.$watch(attr.ngActive, function ngActiveWatchAction(value){
      $animate[value ? 'addClass' : 'removeClass'](element, 'active');
    });
  };
}]);

Plus d'informations

3
lars1595

Si vous utilisez angular avant la v1.1.5 (c’est-à-dire sans opérateur ternaire) et que vous souhaitiez toujours une manière équivalente de définir une valeur dans les deux conditions vous pouvez faire quelque chose comme ceci:

ng-class="{'class1':item.isReadOnly == false, 'class2':item.isReadOnly == true}"
3
Scotty.NET

Vérifier http://www.codinginsight.com/angularjs-if-else-statement/

La tristement célèbre angularjs if else statement !!! Quand j’ai commencé à utiliser Angularjs, j’ai été un peu surpris de ne pas trouver d’instruction if/else.

Donc, je travaillais sur un projet et j'ai remarqué que lors de l'utilisation de l'instruction if/else, la condition apparaît lors du chargement. Vous pouvez utiliser ng-cloak pour résoudre ce problème.

<div class="ng-cloak">
 <p ng-show="statement">Show this line</span>
 <p ng-hide="statement">Show this line instead</span>
</div>

.ng-cloak { display: none }

Merci amadou

3
Victor Cruz

Vous pouvez utiliser le package this npm. Il gère tout et propose des options pour les classes statiques et conditionnelles basées sur une variable ou une fonction.

// Support for string arguments
getClassNames('class1', 'class2');

// support for Object
getClassNames({class1: true, class2 : false});

// support for all type of data
getClassNames('class1', 'class2', ['class3', 'class4'], { 
    class5 : function() { return false; },
    class6 : function() { return true; }
});

<div className={getClassNames({class1: true, class2 : false})} />
0
Tushar Sharma