Conditional logic in AngularJS template

I have an angular template that looks like this:

<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> 

I installed JSfiddle to show related data.

What I need to do is that the divs from "from", "to" and "arrowTo" show conditionally, depending on the contents of the data.

A magazine is ...

  • If there is a "from" object in the data, then display the "from" div and bind the data, but do not show the div "createdBy".
  • If the "from" object is missing, but there is an "createdBy" object, then display the "createdBy" div and bind the data.
  • If the data has a "to" object, then display the "arrowTo" div and anchor it.

Or in plain English, if there is an address, show it, otherwise show who created the record, and if there is an address, also show it.

I studied the use of ng-switch, but I think I would have to add extra markup that would leave an empty div if there was no data. Plus, I would need to set switch directives, and I'm not sure if this will work.

Any ideas?

UPDATE:

If I wrote my own directive (if I knew how!), Then here is some kind of pseudo code to show how I want to use it ...

 <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> 

Each of them will disappear if the function / expression evaluates to false.

+63
javascript angularjs
Dec 29
source share
3 answers

Angular 1.1.5 introduced the ng-if directive. This is the best solution for this particular problem. If you are using an older version of Angular, consider the angular -ui ui-if directive.

If you came here looking for answers to the general question “conditional logic in templates”, also consider:

  • 1.1.5 also introduced the ternary operator
  • ng-switch can be used to conditionally add / remove elements from the DOM
  • see also How to conditionally apply CSS styles in AngularJS?



Original answer:

Here is a not-so-good "ng-if" directive:

 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(' ') } } } }); 

which allows you to use this HTML syntax:

 <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 () is used to remove unnecessary content from the DOM.

Also, as I mentioned on Google+, ng-style can probably be used to conditionally load background images if you want to use ng -show instead of a custom directive. (For the benefit of other readers, John stated on Google+: “Both methods use ng-show, which I am trying to avoid because it uses display: none and leaves extra markup in the DOM. This is a special problem in this scenario because the hidden element will have a background image that will still be loaded in most browsers. ").
See also How to conditionally apply CSS styles in AngularJS?

angular -ui ui-if directive monitors changes in the if / expression condition. My not. Thus, although my simple implementation will correctly update the view, if the model changes so that it only affects the output of the template, it will not correctly update the view if the response of the condition / expression changes.

For example, if the value of a from.name changes in the model, the view will be updated. But if you delete $scope.data.messages[0].from , the name will be removed from the view, but the template will not be removed from the view, because the if-condition / expression is not visible.

+84
Dec 29 '12 at 22:34
source share

You can use the ngSwitch directive:

  <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> 

If you do not want the DOM to load with empty divs, you need to create your custom directive using $ http to load (sub) templates and compile $ to insert it into the DOM when a certain condition is reached.

This is a simple (untested) example. It can and should be optimized:

HTML:

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

Directive

 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() } }; }); 
+20
Dec 29
source share

You can use ng-show for each div element in a loop. This is what you wanted: http://jsfiddle.net/pGwRu/2/ ?

 <div class="from" ng-show="message.from">From: {{message.from.name}}</div> 
+6
Dec 29 2018-12-12T00:
source share



All Articles