238

How do you do a ternary with AngularJS (in the templates)?

It would be nice to use some in html attributes (classes and style) instead of creating and calling a function of the controller.

starcorn
  • 7,071
  • 19
  • 73
  • 118
cricardol
  • 4,211
  • 3
  • 15
  • 28

7 Answers7

373

Update: Angular 1.1.5 added a ternary operator, so now we can simply write

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

If you are using an earlier version of Angular, your two choices are:

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

item 2. above creates an object with two properties. The array syntax is used to select either the property with name true or the property with name false, and return the associated value.

E.g.,

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

$first is set to true inside an ng-repeat for the first element, so the above would apply class 'myClass1' and 'myClass2' only the first time through the loop.

With ng-class there is an easier way though: ng-class takes an expression that must evaluate to one of the following:

  1. a string of space-delimited class names
  2. an array of class names
  3. a map/object of class names to boolean values.

An example of 1) was given above. Here is an example of 3, which I think reads much better:

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

The first time through an ng-repeat loop, class myClass is added. The 3rd time through ($index starts at 0), class anotherClass is added.

ng-style takes an expression that must evaluate to a map/object of CSS style names to CSS values. E.g.,

 <li ng-style="{true: {color: 'red'}, false: {}}[$first]">...</li>
Anthony O.
  • 16,644
  • 12
  • 92
  • 151
Mark Rajcok
  • 348,511
  • 112
  • 482
  • 482
85

Update: Angular 1.1.5 added a ternary operator, this answer is correct only to versions preceding 1.1.5. For 1.1.5 and later, see the currently accepted answer.

Before Angular 1.1.5:

The form of a ternary in angularjs is:

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

An example would be:

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

or:

 <li  ng-disabled="currentPage == 0" ng-click="currentPage=0"  class="{{(currentPage == 0) && 'disabled' || ''}}"><a> << </a></li>
Buhake Sindi
  • 82,658
  • 26
  • 157
  • 220
cricardol
  • 4,211
  • 3
  • 15
  • 28
  • 1
    Weird. That's not very intuitive. I wonder why it was implemented this way. – Ben Lesh Aug 17 '12 at 15:49
  • 4
    Ternary was never implemneted, but this is just using the binary operators the way they work. – Andrew Joslin Aug 17 '12 at 20:09
  • 18
    @blesh, AngularJS promotes testability. Templates should not contain any logic. A ternary operator in a template should be refactored to a function call to the controller, for better testability. – Marcello Nuccio Aug 18 '12 at 07:18
  • Should the above examples be using ng-style and ng-class? (I'm not sure when they need to be used). – Mark Rajcok Aug 18 '12 at 15:12
  • @MarcelloNuccio, +1, makes sense. – Ben Lesh Aug 19 '12 at 02:05
  • @Mark, if you want to use ng-style, then the expression needs to eval to an object whose keys are CSS style names and whose values are the CSS values. E.g., ng-style="{color: $location.path()=='/page2' && '#fff' || '#000'}". I think this reads a bit nicer, since it is easier to tell you are setting 'color'. – Mark Rajcok Aug 28 '12 at 00:25
  • @MarcelloNuccio can you elaborate on that? I want to print css clases according to a boolean property, how would I refactor that to the controller exactly? (i'm a noob, i know) – arg20 Apr 09 '13 at 14:14
  • 1
    @arg20 you should use [ngClass](http://docs.angularjs.org/api/ng.directive:ngClass) directive (or ngClassEven and ngClassOdd). Then put all the logic for choosing css classes in the controller. This is much more easy to test automatically. – Marcello Nuccio Apr 10 '13 at 08:54
  • @MarcelloNuccio but is it a good idea to put classes names on the model? They belong in the view, the model shouldn't be aware of what css classes the view uses. What would be best is if I could use a boolean property from the model, like `ng-class="someboolean: 'myCssClass'"` – arg20 Apr 10 '13 at 12:34
  • 1
    @arg20 I said to put it in the controller, not in the model. This should not be a problem. However, the documentation says: "The result of the evaluation can be a string representing space delimited class names, an array, or a map of class names to boolean values". Meaning that you can use "{ cssclass: someBoolCheck() }" as an expression, i.e. you put the css class in the view, and the logic in the controller. Look at [this jsFiddle](http://jsfiddle.net/MnJX2/) for an example. – Marcello Nuccio Apr 10 '13 at 14:36
  • Perfect. Exactly what I was looking for! Thanks! – incutonez Jul 01 '13 at 13:05
22

For texts in angular template (userType is property of $scope, like $scope.userType):

<span>
  {{userType=='admin' ? 'Edit' : 'Show'}}
</span>
Ikrom
  • 3,635
  • 4
  • 42
  • 68
10

This answer predates version 1.1.5 where a proper ternary in the $parse function wasn't available. Use this answer if you're on a lower version, or as an example of filters:

angular.module('myApp.filters', [])
  
  .filter('conditional', function() {
    return function(condition, ifTrue, ifFalse) {
      return condition ? ifTrue : ifFalse;
    };
  });

And then use it as

<i ng-class="checked | conditional:'icon-check':'icon-check-empty'"></i>
Jan
  • 7,801
  • 3
  • 35
  • 57
  • 2
    I came to this question for the ternary operator but at the end I went with a filter and it felt really good... =D – slacktracer Oct 30 '13 at 17:57
10

While you can use the condition && if-true-part || if-false-part-syntax in older versions of angular, the usual ternary operator condition ? true-part : false-part is available in Angular 1.1.5 and later.

Aleksander Blomskøld
  • 17,546
  • 9
  • 71
  • 82
9

There it is : ternary operator got added to angular parser in 1.1.5! see the changelog

Here is a fiddle showing new ternary operator used in ng-class directive.

ng-class="boolForTernary ? 'blue' : 'red'"
lionroots
  • 274
  • 3
  • 5
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>

Button toggle and change header of button and show/hide div panel. See the Plunkr

Zahid Rahman
  • 1,471
  • 1
  • 15
  • 25