AngularJS ng-class multiple conditions with OR operator

All we need is an easy explanation of the problem, so here it is.

I try to find out the good syntax for adding classes depending on angular values.
I want to activate a class regarding 2 conditions (one on live user changes, and one on loading datas) with a OR operator.

Here is the line :

 <a href="" ng-click=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"addFavorite(myfav.id);favorite=!favorite">
    <i class="fa orange" ng-class="{'fa-star': (favorite || (fav==myfav.id)), 'fa-star-o': !favorite}"></i>
 </a>

I tried some different codes like this one :

 ng-class="{'fa-star': favorite, 'fa-star': (fav==myfav.id), 'fa-star-o': !favorite}"

without any success.
Can someone help me finding the good syntax ?

How to solve :

I know you bored from this bug, So we are here to help you! Take a deep breath and look at the explanation of your problem. We have many solutions to this problem, But we recommend you to use the first method because it is tested & true method that will 100% work for you.

Method 1

Try this.

<a href="" ng-click=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"addFavorite(myfav.id);favorite=!favorite">
 <i class="fa orange" ng-class="{'fa-star': favorite || fav==myfav.id, 'fa-star-o': !favorite}"></i>

No need the brackets.

Method 2

Once you have to add some logic behind ng-class it’s always better to stick to using the controller to do that. You can do it two of either ways: JSON syntax (same as in your HTML, just more readable) or obviously JavaScript.

HTML (JSON) Syntax

HTML

<i ng-class="getFavClassIcon(myFav.id)"></i>

JS

$scope.getFavClassIcon= function (favId) {
    return {
        'fa-star-o' : !$scope.favorite,
        'fa-star'   : $scope.favorite || $scope.fav === favId
    };
};

Good Old IF-statement (JavaScript)

HTML

<i ng-class="getFavClassIcon(myFav.id)"></i>

JS

$scope.getFavClassIcon= function (favId) {
    if (!$scope.favorite) {
        return 'fa-star-o';
    } else if ($scope.favorite) { // obviously you can use OR operator here
        return 'fa-star';
    } else if ($scope.fav === favId) {
        return 'fa-star';
    }
};

Method 3

The HTML will remain the same

<a href="" ng-click=" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener" rel="nofollow noreferrer noopener"addFavorite(myfav.id);favorite=!favorite">
    <i ng-class="{'fa-star-o':!favorite,'fa-star':favorite||fav===myfav.id}"></i>
</a>

But the order in which classes are present in your CSS file will matter

The fa-star class will apply either when favorite is true or fav===myfav.id returns true.

Therefore if after clicking once , suppose fav===myfav.id returns true and keeps on returning true , even when clicking again , then the class fa-star will be applied always from then on.

If by default favorite is false , then fa-star-o will be applied when template is loaded the first time, but after the first click ,when favorite is set to true , it will get removed. Then on second click , when favorite is set to false again , fa-star-o it will get applied but in this case , fa-star class will also be applied as fa===myfav.id condition would be still returning true (Assuming that is the case).

Therefore you will need to prioritize which class needs to get applied for sure when it is present on the element as case can arise when both classes can be present at the same time on the element. For example if fa-star-o class takes higher priority, then put it below the fa-star in your CSS , like for example

.fa-star {
  border: 1px solid #F00;
}
.fa-star-o {
  border: 1px solid #000;
}

See working demo at http://plnkr.co/edit/Dh59KUU41uWpIkHIaYrO?p=preview

Method 4

You can use expression with ng-class

  <i class="fa orange" ng-class="favorite || fav == myfav.id ? 'fav' : 'no-fav'"></i>

Method 5

For example:
In my scenario i need to apply uppercase class in some condition and in some condition i do not need to apply that uppercase class.

inputTextCapitalSmall(assetId) {
    return {
      'uppercase': assetId !== 'TELEKURS' && assetId !== 'REUTERS' && assetId !== 'S&P',
    };
  }

<form [formGroup]="querySearchForm" >
  <input autocomplete="off" matInput id="assetIdTypeValue" [ngClass]="inputTextCapitalSmall(querySearchForm.value.assetIdType)" >
</form>

Note: Use and implement method 1 because this method fully tested our system.
Thank you 🙂

All methods was sourced from stackoverflow.com or stackexchange.com, is licensed under cc by-sa 2.5, cc by-sa 3.0 and cc by-sa 4.0

Leave a Reply