Logique conditionnelle dans le modèle AngularJS

J'ai un modèle angulaire qui ressemble à ça …

<div ng-repeat="message in data.messages" ng-class="message.type"> <div class="info"> <div class="type"></div> <div class="from">From Avatar</div> <div class="createdBy">Created By Avatar</div> <div class="arrowTo"> <div class="arrow"></div> <div class="to">To Avatar</div> </div> <div class="date"> <div class="day">25</div> <div class="month">Dec</div> </div> </div> <div class="main"> <div class="content"> <div class="heading2">{{message.title}}</div> <div ng-bind-html="message.content"></div> </div> </div> <br /> <hr /> <br /> </div> 

J'ai configuré un JSfiddle pour montrer les données liées.

Ce que je dois faire, c'est de diviser les divs "from", "to" et "arrowTo" conditionnellement, selon le contenu des données.

Le journal est ce …

  • S'il y a un objet "de" dans les données, affichez le "de" div et liez les données mais ne montre pas la division "createdBy".
  • S'il n'y a pas d'objet "de", mais il y a un objet "créé", puis affichez la division "crééBy" et liez les données.
  • S'il y a un objet «à» dans les données, indiquez la division «arrowTo» et liez-les.

Ou en anglais simple, s'il y a une adresse, affichez-le, sinon, indiquez qui a créé l'enregistrement à la place et si il y a une adresse, puis indiquez cela.

J'ai cherché à utiliser ng-switch, mais je pense que je devrais ajouter une marquage supplémentaire qui laisserait une division vide si il n'y avait pas de données. De plus, je devrais imbriquer les directives de commutation et je ne sais pas si cela fonctionnerait.

Des idées?

METTRE À JOUR:

Si je devais écrire ma propre directive (si je savais comment!), Voici un pseudo code pour montrer comment je voudrais l'utiliser …

 <div ng-if="showFrom()"> From Template Goes Here </div> <div ng-if="showCreatedBy()"> CreatedBy Template Goes Here </div> <div ng-if="showTo()"> To Template Goes Here </div> 

Chacun d'entre eux disparaitrait si la fonction / expression évaluée était fausse.

Angular 1.1.5 a introduit la directive ng-if . C'est la meilleure solution pour ce problème particulier. Si vous utilisez une ancienne version d'Angular, envisagez d'utiliser la directive ui-if d' angular-ui.

Si vous êtes arrivé ici à la recherche de réponses à la question générale de «logique conditionnelle dans les modèles», considérons également:

  • 1.1.5 a également introduit un opérateur ternaire
  • Ng-switch peut être utilisé pour ajouter / supprimer conditionnellement les éléments du DOM
  • Voir aussi Comment applique-t-on conditionnellement les styles CSS dans AngularJS?

Réponse originale:

Voici une directive "ng-if" pas trop géniale:

 myApp.directive('ngIf', function() { return { link: function(scope, element, attrs) { if(scope.$eval(attrs.ngIf)) { // remove '<div ng-if...></div>' element.replaceWith(element.children()) } else { element.replaceWith(' ') } } } }); 

Qui permet cette syntaxe HTML:

 <div ng-repeat="message in data.messages" ng-class="message.type"> <hr> <div ng-if="showFrom(message)"> <div>From: {{message.from.name}}</div> </div> <div ng-if="showCreatedBy(message)"> <div>Created by: {{message.createdBy.name}}</div> </div> <div ng-if="showTo(message)"> <div>To: {{message.to.name}}</div> </div> </div> 

Fiddle .

ReplaceWith () est utilisé pour supprimer le contenu non nécessaire du DOM.

En outre, comme je l'ai mentionné sur Google+, le style ng peut probablement être utilisé pour charger conditionnellement des images d'arrière-plan, si vous souhaitez utiliser ng-show au lieu d'une directive personnalisée. (Pour le bénéfice d'autres lecteurs, Jon a déclaré sur Google+: "les deux méthodes utilisent ng-show que j'essaie d'éviter car elles utilisent l'affichage: aucune et laisse des balises supplémentaires dans les DOM. C'est un problème particulier dans ce scénario parce que L'élément caché aura une image d'arrière-plan qui sera encore chargée dans la plupart des navigateurs. ").
Voir aussi Comment puis-je appliquer conditionnellement les styles CSS dans AngularJS?

La directive angular-ui ui-if surveille les modifications de la condition / expression if. Le mien ne le fait pas. Ainsi, alors que ma mise en œuvre simple mettra à jour correctement la vue si le modèle change de sorte qu'il affecte uniquement la sortie du modèle, il ne mettra pas à jour la vue correctement si la réponse condition / expression change.

Par exemple, si la valeur d'un from.name change dans le modèle, la vue sera mise à jour. Mais si vous delete $scope.data.messages[0].from , le nom de l'utilisateur sera supprimé de la vue, mais le modèle ne sera pas supprimé de la vue car la condition / expression if n'est pas surveillée.

Vous pouvez utiliser la directive ngSwitch :

  <div ng-switch on="selection" > <div ng-switch-when="settings">Settings Div</div> <span ng-switch-when="home">Home Span</span> <span ng-switch-default>default</span> </div> 

Si vous ne souhaitez pas que le DOM soit chargé avec des divs vides, vous devez créer votre directive personnalisée en utilisant $ http pour charger les modèles (sous) et $ compiler pour l'injecter dans le DOM quand une certaine condition est atteinte.

Ce n'est qu'un exemple (non testé). Il peut et devrait être optimisé:

HTML:

 <conditional-template ng-model="element" template-url1="path/to/partial1" template-url2="path/to/partial2"></div> 

Directif:

 app.directive('conditionalTemplate', function($http, $compile) { return { restrict: 'E', require: '^ngModel', link: function(sope, element, attrs, ctrl) { // get template with $http // check model via ctrl.$viewValue // compile with $compile // replace element with element.replaceWith() } }; }); 

Vous pouvez utiliser ng-show sur chaque élément div dans la boucle. Est-ce ce que vous vouliez: http://jsfiddle.net/pGwRu/2/ ?

 <div class="from" ng-show="message.from">From: {{message.from.name}}</div>