AngularJS ngClass conditional

Is there any way to make an expression for something like ng-class to be a conditional?

For example, I have tried the following:

<span ng-class="{test: 'obj.value1 == \'someothervalue\''}">test</span>

The issue with this code is that no matter what obj.value1 is, the class test is always applied to the element. Doing this:

<span ng-class="{test: obj.value2}">test</span>

As long as obj.value2 does not equal a truthy value, the class in not applied. Now I can work around the issue in the first example by doing this:

<span ng-class="{test: checkValue1()}">test</span>

Where the checkValue1 function looks like this:

$scope.checkValue1 = function() {
  return $scope.obj.value === 'somevalue';
}

I am just wondering if this is how ng-class is supposed to work. I am also building a custom directive where I would like to do something similar to this. However, I can't find a way to watch an expression (and maybe that is impossible and the reason why it works like this).

Here is a plnkr to show what I mean.


Solution 1:

Your first attempt was almost right, It should work without the quotes.

{test: obj.value1 == 'someothervalue'}

Here is a plnkr.

The ngClass directive will work with any expression that evaluates truthy or falsey, a bit similar to Javascript expressions but with some differences, you can read about here. If your conditional is too complex, then you can use a function that returns truthy or falsey, as you did in your third attempt.

Just to complement: You can also use logical operators to form logical expressions like

ng-class="{'test': obj.value1 == 'someothervalue' || obj.value2 == 'somethingelse'}"

Solution 2:

Using ng-class inside ng-repeat

<table>
    <tbody>
            <tr ng-repeat="task in todos"
                ng-class="{'warning': task.status == 'Hold' , 'success': task.status == 'Completed',
              'active': task.status == 'Started', 'danger': task.status == 'Pending' } ">
                <td>{{$index + 1}}</td>
                <td>{{task.name}}</td>
                <td>{{task.date|date:'yyyy-MM-dd'}}</td>
                <td>{{task.status}}</td>
            </tr>
    </tbody>
</table>

For each status in task.status a different class is used for the row.

Solution 3:

Angular JS provide this functionality in ng-class Directive. In which you can put condition and also assign conditional class. You can achieve this in two different ways.

Type 1

<div ng-class="{0:'one', 1:'two',2:'three'}[status]"></div>

In this code class will be apply according to value of status value

if status value is 0 then apply class one

if status value is 1 then apply class two

if status value is 2 then apply class three


Type 2

<div ng-class="{1:'test_yes', 0:'test_no'}[status]"></div>

In which class will be apply by value of status

if status value is 1 or true then it will add class test_yes

if status value is 0 or false then it will add class test_no

Solution 4:

I see great examples above but they all start with curly brackets (json map). Another option is to return a result based on computation. The result can also be a list of css class names (not just map). Example:

ng-class="(status=='active') ? 'enabled' : 'disabled'"

or

ng-class="(status=='active') ? ['enabled'] : ['disabled', 'alik']"

Explanation: If the status is active, the class enabled will be used. Otherwise, the class disabled will be used.

The list [] is used for using multiple classes (not just one).

Solution 5:

There is a simple method which you could use with html class attribute and shorthand if/else. No need to make it so complex. Just use following method.

<div class="{{expression == true ? 'class_if_expression_true' : 'class_if_expression_false' }}">Your Content</div>