conditions en ligne dans angular.js


192

Je me demandais s'il y avait un moyen angulaire d'afficher conditionnellement du contenu autre que l'utilisation de ng-show, etc. Par exemple, dans backbone.js, je pourrais faire quelque chose avec du contenu en ligne dans un modèle comme:

<% if (myVar === "two") { %> show this<% } %>

mais en angulaire, je semble être limité à montrer et cacher les choses enveloppées dans des balises html

<p ng-hide="true">I'm hidden</p>
<p ng-show="true">I'm shown</p>

Quelle est la méthode recommandée en angulaire pour afficher et masquer de manière conditionnelle le contenu en ligne en angulaire en utilisant simplement {{}} plutôt que d'envelopper le contenu dans des balises html?


6
veuillez refuser ma réponse et accepter les 2Toad lorsque vous en aurez l'occasion.
Ben Lesh

Réponses:


139

EDIT: la réponse de 2Toad ci - dessous est ce que vous cherchez! Votez cette chose

Si vous utilisez Angular <= 1.1.4, cette réponse fera l'affaire:

Encore une réponse à cela. Je poste une réponse distincte, car il s'agit plus d'une tentative "exacte" de solution que d'une liste de solutions possibles:

Voici un filtre qui fera un "si immédiat" (alias iif):

app.filter('iif', function () {
   return function(input, trueValue, falseValue) {
        return input ? trueValue : falseValue;
   };
});

et peut être utilisé comme ceci:

{{foo == "bar" | iif : "it's true" : "no, it's not"}}

Merci blesh, c'est ce que j'allais faire. Cependant, je remarque que si j'essaie de mettre une balise html dans l'une des valeurs, elle casse: {{thing.second == "two" | iif: "<ul class = 'two-class'>": "<ul>"}} Je me rends compte qu'il peut y avoir de meilleures façons de le faire en angulaire, mais existe-t-il un moyen d'échapper à "<" et ">" afin que les balises puissent être sorties dans le cadre de la chaîne?
user1469779

1
ngBind n'autorise pas la sortie HTML, vous voudriez utiliser ng-bind-html-unsafe
Ben Lesh

L'exemple de ng-binf-html-unsafe dans la documentation angulaire l'utilise dans une balise, par exemple <ANY ng-bind-html-unsafe = "{expression}">. il n'est peut-être pas possible de faire ce que j'essaie de faire en ligne.
user1469779

1
IIF est l'abréviation de "Inline If". Il est courant dans différents langages de programmation ... mais pas aussi commun que?: If en ligne. ;)
Ben Lesh

18
@BenLesh principaux accessoires pour modifier votre réponse maintenant qu'il existe d'autres options, bon travail.
Nick Coad

724

Angular 1.1.5 a ajouté la prise en charge des opérateurs ternaires:

{{myVar === "two" ? "it's true" : "it's false"}}

14
Cette réponse avec le plus de votes devrait apparaître en haut des réponses ... c'est de loin la plus correcte
Code Whisperer

3
user1469779 envisagez d'accepter cette réponse car c'est la façon recommandée d'atteindre ce que vous voulez pendant un certain temps
Filip Kis

13
@ 2Toad, ma réponse était ancienne. c'est la bonne réponse maintenant, je ne sais pas si l'utilisateur sera de retour pour "l'accepter" maintenant, mais j'ai annoté ma réponse comme telle. Tel est le visage changeant du développement logiciel.
Ben Lesh

2
Merci. Comment puis-je lui faire afficher la valeur de myVarseulement si elle est fausse? (c'est-à-dire comment puis-je imbriquer des variables dans l'expression?) J'ai essayé avec {{myVar === "two" ? "it's true" : {{myVar}}}}mais cela ne fonctionne pas.
Josh

6
@Josh, la myVarpropriété n'a pas besoin d'être entourée d'accolades supplémentaires, elle est déjà à l'intérieur d'une expression. Essayez{{myVar === "two" ? "it's true" : myVar}}
2Toad

60

Des milliers de façons d'écorcher ce chat. Je me rends compte que vous posez des questions spécifiques entre {{}}, mais pour ceux qui viennent ici, je pense que cela vaut la peine de montrer certaines des autres options.

fonction sur votre portée $ (IMO, c'est votre meilleur pari dans la plupart des scénarios):

  app.controller('MyCtrl', function($scope) {
      $scope.foo = 1;

      $scope.showSomething = function(input) {
           return input == 1 ? 'Foo' : 'Bar';
      };
   });

 <span>{{showSomething(foo)}}</span>

ng-show et ng-hide bien sûr:

 <span ng-show="foo == 1">Foo</span><span ng-hide="foo == 1">Bar</span>

ngSwitch

 <div ng-switch on="foo">
   <span ng-switch-when="1">Foo</span>
   <span ng-switch-when="2">Bar</span>
   <span ng-switch-default>What?</span>
 </div>

Un filtre personnalisé comme l'a suggéré Bertrand. (c'est votre meilleur choix si vous devez faire la même chose encore et encore)

app.filter('myFilter', function() {
   return function(input) {
     return input == 1 ? 'Foo' : 'Bar';
   }
}

{{foo | myFilter}}

Ou une directive personnalisée:

app.directive('myDirective', function() {
   return {
     restrict: 'E',
     replace: true,
     link: function(scope, elem, attrs) {
       scope.$watch(attrs.value, function(v) {
          elem.text(v == 1 ? 'Foo': 'Bar');
       });
     }
   };
});


<my-directive value="foo"></my-directive>

Personnellement, dans la plupart des cas, j'irais avec une fonction sur ma portée, cela garde le balisage assez propre et il est rapide et facile à implémenter. À moins que vous ne fassiez la même chose encore et encore, auquel cas j'irais avec la suggestion de Bertrand et créerais un filtre ou éventuellement une directive, selon les circonstances.

Comme toujours, la chose la plus importante est que votre solution est facile à entretenir et peut être testée, espérons-le. Et cela va dépendre complètement de votre situation spécifique.


18

J'utilise ce qui suit pour définir conditionnellement la classe attr lorsque la classe ng ne peut pas être utilisée (par exemple lors du style SVG):

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

La même approche devrait fonctionner pour d'autres types d'attributs.

(Je pense que vous devez être sur le dernier Angular instable pour utiliser ng-attr-, je suis actuellement sur 1.1.4)

J'ai publié un article sur le travail avec AngularJS + SVG qui parle de cela et des problèmes connexes. http://www.codeproject.com/Articles/709340/Implementing-a-Flowchart-with-SVG-and-AngularJS


15

Pour vérifier un contenu variable et avoir un texte par défaut, vous pouvez utiliser:

<span>{{myVar || 'Text'}}</span>

1
Merci! J'essayais cela mais je manque les guillemets autour de la chaîne :-)
Simona Adriani

Pour une raison quelconque, cette syntaxe ne fonctionne pas en utilisant des liaisons uniques. {{:: myVar || 'Text'}} ne fonctionnera pas. Doit être sans ::
aoakeson

3

Si je vous ai bien compris, je pense que vous avez deux façons de procéder.

Vous pouvez d'abord essayer ngSwitch et la deuxième façon possible serait de créer votre propre filtre . Probablement, ngSwitch est la bonne approche, mais si vous voulez masquer ou afficher du contenu en ligne en utilisant simplement le filtre {{}}, c'est la voie à suivre.

Voici un violon avec un simple filtre comme exemple.

<div ng-app="exapleOfFilter">
  <div ng-controller="Ctrl">
    <input ng-model="greeting" type="greeting">
      <br><br>
      <h1>{{greeting|isHello}}</h1>
  </div>
</div>

angular.module('exapleOfFilter', []).
  filter('isHello', function() {
    return function(input) {
      // conditional you want to apply
      if (input === 'hello') {
        return input;
      }
      return '';
    }
  });

function Ctrl($scope) {
  $scope.greeting = 'hello';
}

3

La bibliothèque de l'interface utilisateur angulaire a une directive intégrée ui-if pour la condition dans le modèle / Vues jusqu'à l'interface utilisateur angulaire 1.1.4

Exemple: prise en charge de l'interface utilisateur angulaire jusqu'à l'interface utilisateur 1.1.4

<div ui-if="array.length>0"></div>

ng-si disponible dans toute la version angulaire après 1.1.4

<div ng-if="array.length>0"></div>

si vous avez des données dans une variable de tableau, seul le div apparaîtra


ui-ifa été supprimé au moins de la dernière version angular-ui mais depuis angular 1.1.5 vous avez ng-if(de ce commentaire )
Dave Everitt

2

Donc avec Angular 1.5.1 (avait une dépendance d'application existante sur d'autres dépendances de la pile MEAN, c'est pourquoi je n'utilise pas actuellement 1.6.4)

Cela fonctionne pour moi comme le dit l'OP {{myVar === "two" ? "it's true" : "it's false"}}

{{vm.StateName === "AA" ? "ALL" : vm.StateName}}

2

si vous voulez afficher "Aucun" lorsque la valeur est "0", vous pouvez utiliser comme:

<span> {{ $scope.amount === "0" ?  $scope.amount : "None" }} </span>

ou vrai faux en js angulaire

<span> {{ $scope.amount === "0" ?  "False" : "True" }} </span>

1

Fonctionne même dans des situations exotiques:

<br ng-show="myCondition == true" />

0

Je vais jeter le mien dans le mix:

https://gist.github.com/btm1/6802312

ceci évalue l'instruction if une fois et n'ajoute aucun écouteur de surveillance MAIS vous pouvez ajouter un attribut supplémentaire à l'élément qui a le set-if appelé wait-for = "somedata.prop" et il attendra que ces données ou propriétés soient définies avant évaluer l'instruction if une fois. cet attribut supplémentaire peut être très pratique si vous attendez des données d'une demande XHR.

angular.module('setIf',[]).directive('setIf',function () {
    return {
      transclude: 'element',
      priority: 1000,
      terminal: true,
      restrict: 'A',
      compile: function (element, attr, linker) {
        return function (scope, iterStartElement, attr) {
          if(attr.waitFor) {
            var wait = scope.$watch(attr.waitFor,function(nv,ov){
              if(nv) {
                build();
                wait();
              }
            });
          } else {
            build();
          }

          function build() {
            iterStartElement[0].doNotMove = true;
            var expression = attr.setIf;
            var value = scope.$eval(expression);
            if (value) {
              linker(scope, function (clone) {
                iterStartElement.after(clone);
                clone.removeAttr('set-if');
                clone.removeAttr('wait-for');
              });
            }
          }
        };
      }
    };
  });
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.