instruction if else dans les modèles AngularJS

702

Je veux faire une condition dans un modèle AngularJS. Je récupère une liste de vidéos depuis l'API Youtube. Certaines vidéos sont au format 16: 9 et d'autres au format 4: 3.

Je veux faire une condition comme ça:

if video.yt$aspectRatio equals widescreen then 
    element's attr height="270px"
else
    element's attr height="360px"

J'itère les vidéos en utilisant ng-repeat. Je n'ai aucune idée de ce que je dois faire pour cette condition:

  • Ajouter une fonction dans la portée?
  • Faites-le dans le modèle?
vzhen
la source
2
J'ai trouvé un article ng-if ici. goo.gl/wQ30uf
virender

Réponses:

1284

Angularjs (versions inférieures à 1.1.5) ne fournit pas la if/elsefonctionnalité. Voici quelques options à considérer pour ce que vous voulez réaliser:

( Passez à la mise à jour ci-dessous (# 5) si vous utilisez la version 1.1.5 ou supérieure )

1. Opérateur ternaire:

Comme suggéré par @Kirk dans les commentaires, la façon la plus propre de le faire serait d'utiliser un opérateur ternaire comme suit:

<span>{{isLarge ? 'video.large' : 'video.small'}}</span>

2. ng-switchdirective:

peut être utilisé quelque chose comme ce qui suit.

<div ng-switch on="video">
    <div ng-switch-when="video.large">
        <!-- code to render a large video block-->
    </div>
    <div ng-switch-default>
        <!-- code to render the regular video block -->
    </div>
</div>

3. ng-hide/ ng-showdirectives

Alternativement, vous pouvez également utiliser, ng-show/ng-hidemais son utilisation rendra à la fois une grande vidéo et un petit élément vidéo, puis masquera celle qui remplit la ng-hidecondition et affiche celle qui remplit la ng-showcondition. Donc, sur chaque page, vous allez réellement afficher deux éléments différents.

4. Une autre option à considérer est la ng-classdirective.

Cela peut être utilisé comme suit.

<div ng-class="{large-video: video.large}">
    <!-- video block goes here -->
</div>

Ce qui précède ajoutera essentiellement une large-videoclasse css à l'élément div s'il video.largeest véridique.

MISE À JOUR: Angular 1.1.5 a introduit lengIf directive

5. ng-ifdirective:

Dans les versions ci-dessus, 1.1.5vous pouvez utiliser la ng-ifdirective. Cela supprimerait l'élément si l'expression fournie retourne falseet réinsère le elementdans le DOM si l'expression revient true. Peut être utilisé comme suit.

<div ng-if="video == video.large">
    <!-- code to render a large video block-->
</div>
<div ng-if="video != video.large">
    <!-- code to render the regular video block -->
</div>
Un mythe
la source
9
Cela devrait être à la ng-switch on="video"placeng-switch-on="video"
czerasz
4
Comment ça? if () {} else if () {} else if () {} else {} Mais n'incluez dans dom qu'un seul élément
falko
208
Aussi ternaire<span>{{isAdded ? 'Added' : 'Add to cart'}}</span>
Kirk Strobeck
16
Gardez à l'esprit que ng-ifcela n'ajoutera PAS les éléments joints au DOM jusqu'à ce que sa condition soit évaluée à true, contrairement à ng-hideet ng-show.
Wilhelm Murdoch
1
Pourquoi pas simplement ng-switch="video"? Quelques problèmes? ou il n'était pas disponible plus tôt? Pour moi ça marche très bien
Sami
175

Dans la dernière version d'Angular (à partir du 1.1.5), ils ont inclus une directive conditionnelle appelée ngIf. Il est différent ngShowet ngHideen ce sens que les éléments ne sont pas cachés, mais pas du tout inclus dans le DOM. Ils sont très utiles pour les composants dont la création est coûteuse mais qui ne sont pas utilisés:

<div ng-if="video == video.large">
    <!-- code to render a large video block-->
</div>
<div ng-if="video != video.large">
    <!-- code to render the regular video block -->
</div>
Brian Genisio
la source
5
Gardez à l'esprit que cela ng-ifintroduit une portée isolée , de sorte que cela $parentdevient $parent.$parentdans le corps de ng-if.
David Salamon
142

Ternary est le moyen le plus clair de le faire.

<div>{{ConditionVar ? 'varIsTrue' : 'varIsFalse'}}</div>
Oliver Dixon
la source
Comment faire cela avec 2 conditions dans ou ?? comme <div> {{A == B || A == C? 'varIsTrue': 'varIsFalse'}} </div>
YoBre
2
Wrap it (A == B || A == C)
Oliver Dixon
1
j'adore cette réponse! L'utilisation des directives ng- donne beaucoup d'espace blanc html si un div ne remplit pas la condition ..
sksallaj
48

Angular lui-même ne fournit pas de fonctionnalité if / else, mais vous pouvez l'obtenir en incluant ce module:

https://github.com/zachsnow/ng-elif

Dans ses propres mots, c'est juste "une simple collection de directives de flux de contrôle: ng-if, ng-else-if et ng-else". C'est simple et intuitif à utiliser.

Exemple:

<div ng-if="someCondition">
    ...
</div>
<div ng-else-if="someOtherCondition">
    ...
</div>
<div ng-else>
    ...
</div>
lpappone
la source
1
je ne veux pas répéter le code dans div encore et encore.
1
Vous n'avez rien à répéter - vous pouvez le faire aussi facilement ng-if="someCondition && someOtherCondition". Peut-être que je me méprends? (Je l' ai écrit ce module - il devrait fonctionner comme ifet elseà JS).
Zach Snow
1
C'est une bouée de sauvetage absolue. Cela devrait faire partie du noyau angulaire, il est indispensable dans le codage des modèles. Bien plus propre que d'avoir des opérateurs ternaires partout, et surmonte les limitations de ng-switch ne pouvant pas évaluer les expressions.
Nico Westerdale
Merci @NicoWesterdale! En outre, j'ai ajouté une version plus riche de ng-switch que vous pourriez trouver utile: github.com/zachsnow/ng-cases
Zach Snow
30

Vous pouvez utiliser votre video.yt$aspectRatio propriété directement en la passant dans un filtre et en liant le résultat à l'attribut height de votre modèle.

Votre filtre ressemblerait à quelque chose comme:

app.filter('videoHeight', function () {
  return function (input) {
    if (input === 'widescreen') {
      return '270px';
    } else {
      return '360px';
    }
  };
});

Et le modèle serait:

<video height={{video.yt$aspectRatio | videoHeight}}></video>
Noah Freitas
la source
Que diriez-vous de votre code lorsqu'il video.yt$aspectRatioest vide ou indéfini? Est-il possible d'appliquer une valeur par défaut?
Fractaliste
13

Dans ce cas, vous souhaitez «calculer» une valeur de pixel en fonction d'une propriété d'objet.

Je définirais une fonction dans le contrôleur qui calcule les valeurs des pixels.

Dans le contrôleur:


$scope.GetHeight = function(aspect) {
   if(bla bla bla) return 270;
   return 360;
}

Ensuite, dans votre modèle, vous écrivez simplement:


element height="{{ GetHeight(aspect) }}px "
Spock
la source
11

Je suis d'accord qu'un ternaire est extrêmement propre. Il semble que cela soit très situationnel, mais comme je dois parfois afficher div ou p ou table, donc avec une table, je ne préfère pas un ternaire pour des raisons évidentes. Faire un appel à une fonction est généralement idéal ou dans mon cas, je l'ai fait:

<div ng-controller="TopNavCtrl">
        <div ng-if="info.host ==='servername'">
            <table class="table">
                <tr ng-repeat="(group, status) in user.groups">
                    <th style="width: 250px">{{ group }}</th>
                    <td><input type="checkbox" ng-model="user.groups[group]" /></td>
                </tr>
            </table>
        </div>
       <div ng-if="info.host ==='otherservername'">
            <table class="table">
                <tr ng-repeat="(group, status) in user.groups">
                    <th style="width: 250px">{{ group }}</th>
                    <td><input type="checkbox" ng-model="user.groups[group]" /></td>
                </tr>
            </table>
        </div>
</div>
Tom Stickel
la source
4
    <div ng-if="modeldate==''"><span ng-message="required" class="change">Date is required</span> </div>

vous pouvez utiliser la directive ng-if comme ci-dessus.

JBhardwaj
la source
3

Une possibilité pour Angular: j'ai dû inclure une instruction if - dans la partie html, j'ai dû vérifier si toutes les variables d'une URL que je produis sont définies. Je l'ai fait de la manière suivante et cela semble être une approche flexible. J'espère que ce sera utile pour quelqu'un.

La partie html dans le modèle:

    <div  *ngFor="let p of poemsInGrid; let i = index" >
        <a [routerLink]="produceFassungsLink(p[0],p[3])" routerLinkActive="active">
    </div>

Et la partie dactylographiée:

  produceFassungsLink(titel: string, iri: string) {
      if(titel !== undefined && iri !== undefined) {
         return titel.split('/')[0] + '---' + iri.split('raeber/')[1];
      } else {
         return 'Linkinformation has not arrived yet';
      }
  }

Merci et meilleures salutations,

Jan

Jan Clemens Stoffregen
la source
2
Ressemble plus à Angular qu'à AngularJS.
pzaenger
@pzaenger, oui, mais de nombreuses réponses à cette question fonctionnent pour les deux, donc je pense que certaines personnes, comme moi, regardent quand même les réponses. Veuillez me le faire savoir si cela vous dérange.
Jan Clemens Stoffregen,
2
Bien. Vous devriez au moins le mentionner dans votre réponse.
pzaenger
@pzaenger, merci pour cet indice, je l'ai mentionné maintenant.
Jan Clemens Stoffregen
1

ng instruction If else

ng-if="receiptData.cart == undefined ? close(): '' ;"
Aamir Anwar
la source