Opérateur ternaire dans les modèles AngularJS

239

Comment faites-vous un ternaire avec AngularJS (dans les modèles)?

Ce serait bien d'utiliser certains attributs HTML (classes et style) au lieu de créer et d'appeler une fonction du contrôleur.

cricardol
la source

Réponses:

374

Mise à jour : Angular 1.1.5 a ajouté un opérateur ternaire , donc maintenant nous pouvons simplement écrire

<li ng-class="$first ? 'firstRow' : 'nonFirstRow'">

Si vous utilisez une version antérieure d'Angular, vos deux choix sont:

  1. (condition && result_if_true || !condition && result_if_false)
  2. {true: 'result_if_true', false: 'result_if_false'}[condition]

l'élément 2. ci-dessus crée un objet avec deux propriétés. La syntaxe du tableau est utilisée pour sélectionner la propriété portant le nom true ou la propriété portant le nom false et renvoyer la valeur associée.

Par exemple,

<li class="{{{true: 'myClass1 myClass2', false: ''}[$first]}}">...</li>
 or
<li ng-class="{true: 'myClass1 myClass2', false: ''}[$first]">...</li>

$ first est défini sur true dans une répétition ng pour le premier élément, donc ce qui précède n'appliquerait les classes 'myClass1' et 'myClass2' que la première fois dans la boucle.

Avec la classe ng, il existe un moyen plus simple: la classe ng prend une expression qui doit correspondre à l'une des valeurs suivantes:

  1. une chaîne de noms de classe délimités par des espaces
  2. un tableau de noms de classe
  3. un mappage / objet des noms de classe aux valeurs booléennes.

Un exemple de 1) a été donné ci-dessus. Voici un exemple de 3, qui je pense se lit beaucoup mieux:

 <li ng-class="{myClass: $first, anotherClass: $index == 2}">...</li>

La première fois dans une boucle ng-repeat, la classe myClass est ajoutée. La 3ème fois ($ index commence à 0), la classe anotherClass est ajoutée.

ng-style prend une expression qui doit s'évaluer en une carte / un objet de noms de style CSS en valeurs CSS. Par exemple,

 <li ng-style="{true: {color: 'red'}, false: {}}[$first]">...</li>
Mark Rajcok
la source
6
Si je pouvais, je vous voterais à nouveau pour avoir mis à jour la question!
Narretz
2
Je m'en occupe, @Narretz.
Ian Hunter
1
Dans l'exemple d'accès à la clé d'objet, vous pouvez ignorer la clé "false" car il s'agit de toute façon d'une chaîne vide.
0xc0de
Avertissement, la version 1.1.5 n'est pas stable actuellement.
Adam Grant
Que faire si le conditionnel change lorsque votre modèle est mis à jour? Je voudrais que le soit mis ng-styleà jour, mais il ne semble être évalué que lorsque l'élément est rendu pour la première fois. (Noob angulaire ici)
Hartley Brody
86

Mise à jour: Angular 1.1.5 a ajouté un opérateur ternaire, cette réponse est correcte uniquement pour les versions antérieures à 1.1.5. Pour 1.1.5 et versions ultérieures, voir la réponse actuellement acceptée.

Avant Angular 1.1.5:

La forme d'un ternaire dans angularjs est:

((condition) && (answer if true) || (answer if false))

Un exemple serait:

<ul class="nav">
    <li>
        <a   href="#/page1" style="{{$location.path()=='/page2' && 'color:#fff;' || 'color:#000;'}}">Goals</a>
    </li>
    <li>
        <a   href="#/page2" style="{{$location.path()=='/page2' && 'color:#fff;' || 'color:#000;'}}">Groups</a>
    </li>
</ul>

ou:

 <li  ng-disabled="currentPage == 0" ng-click="currentPage=0"  class="{{(currentPage == 0) && 'disabled' || ''}}"><a> << </a></li>
cricardol
la source
1
Bizarre. Ce n'est pas très intuitif. Je me demande pourquoi il a été mis en œuvre de cette façon.
Ben Lesh
4
Ternary n'a jamais été implémenté, mais il s'agit simplement d'utiliser les opérateurs binaires comme ils fonctionnent.
Andrew Joslin
18
@blesh, AngularJS favorise la testabilité. Les modèles ne doivent contenir aucune logique. Un opérateur ternaire dans un modèle doit être refactorisé en un appel de fonction au contrôleur, pour une meilleure testabilité.
Marcello Nuccio
1
@ arg20, vous devez utiliser la directive ngClass (ou ngClassEven et ngClassOdd). Ensuite, mettez toute la logique pour choisir les classes CSS dans le contrôleur. C'est beaucoup plus facile à tester automatiquement.
Marcello Nuccio
1
@ arg20 J'ai dit de le mettre dans le contrôleur, pas dans le modèle. Ca ne devrait pas être un problème. Cependant, la documentation indique: "Le résultat de l'évaluation peut être une chaîne représentant des noms de classe séparés par des espaces, un tableau ou une mappe de noms de classe aux valeurs booléennes". Cela signifie que vous pouvez utiliser "{cssclass: someBoolCheck ()}" comme expression, c'est-à-dire que vous mettez la classe css dans la vue et la logique dans le contrôleur. Regardez ce jsFiddle pour un exemple.
Marcello Nuccio
23

Pour les textes dans un modèle angulaire ( userTypeest la propriété de $ scope, comme $ scope.userType):

<span>
  {{userType=='admin' ? 'Edit' : 'Show'}}
</span>
Ikrom
la source
11

À présent, nous avons tous découvert que la version 1.1.5 est livrée avec un ternaire approprié dans la $parsefonction, utilisez simplement cette réponse comme exemple de filtres:

angular.module('myApp.filters', [])

  .filter('conditional', function() {
    return function(condition, ifTrue, ifFalse) {
      return condition ? ifTrue : ifFalse;
    };
  });

Et puis utilisez-le comme

<i ng-class="checked | conditional:'icon-check':'icon-check-empty'"></i>
Jan
la source
2
Je suis venu à cette question pour l'opérateur ternaire mais à la fin je suis allé avec un filtre et c'était vraiment bien ... = D
slacktracer
10

Voilà: l'opérateur ternaire a été ajouté à l'analyseur angulaire dans 1.1.5 ! voir le changelog

Voici un violon montrant un nouvel opérateur ternaire utilisé dans la directive ng-class.

ng-class="boolForTernary ? 'blue' : 'red'"
lionroots
la source
10

Bien que vous puissiez utiliser la condition && if-true-part || if-false-partsyntaxe -sync dans les anciennes versions d'angular, l'opérateur ternaire habituel condition ? true-part : false-partest disponible dans Angular 1.1.5 et versions ultérieures .

Aleksander Blomskøld
la source
0
  <body ng-app="app">
  <button type="button" ng-click="showme==true ? !showme :showme;message='Cancel Quiz'"  class="btn btn-default">{{showme==true ? 'Cancel Quiz': 'Take a Quiz'}}</button>
    <div ng-show="showme" class="panel panel-primary col-sm-4" style="margin-left:250px;">
      <div class="panel-heading">Take Quiz</div>
      <div class="form-group col-sm-8 form-inline" style="margin-top: 30px;margin-bottom: 30px;">

        <button type="button" class="btn btn-default">Start Quiz</button>
      </div>
    </div>
  </body>

Bouton bascule et modifie l'en-tête du bouton et affiche / masque le panneau div. Voir le Plunkr

Zahid Rahman
la source