Shiny
Shiny

Reputation: 105

angularjs - ng-if Multiple Conditions

So this has been asked before but my question isnt as simple as ng-if="country == 'ireland' || country='United Kingdom'"

I need to do something like:

ng-if="(country='ireland' || country='united kingdom') || (name='John' || name='Joe')"

What im doing is this:
ng-if=" (settings.eur && title.usa != undefined || title.leak != undefined) || (settings.usa && title.eur != undefined || title.leak != undefined) || (settings.leak && title.eur != undefined || title.usa != undefined) || (settings.leak == false && settings.eur == false && settings.usa == false)"

But it's only triggering the first line or at least that is what it seems to be doing.

Upvotes: 3

Views: 31786

Answers (4)

Sᴀᴍ Onᴇᴌᴀ
Sᴀᴍ Onᴇᴌᴀ

Reputation: 8297

There are a few things to consider here:

Assignment operator vs equality operator

Use the javascript equality operator (i.e. ==) instead of assignment operator (i.e. =):

ng-if="(country=='ireland' || country=='united kingdom') || (name=='John' || name=='Joe')"

Operator Precedence and Associativity

Additionally, consider operator precedence - whether the conditions joined with the logical AND (i.e. &&) should be evaluated before those joined via logical OR (i.e. ||). Use the grouping operators (i.e. ( and ) - A.K.A. parentheses) to use right-associativity when needed.

For instance, this line:

(settings.eur && title.usa != undefined || title.leak != undefined)

Could be altered for right-associativity:

(settings.eur && (title.usa != undefined || title.leak != undefined))

Or to keep left-assciativity:

((settings.eur && title.usa != undefined) || title.leak != undefined)

Move logic to controller

As has been mentioned in comments, the logic in that large conditional should likely be moved into some controller logic. This will make it simpler to update and separate the business logic from the markup.

One way to do that is to declare a function like in the example below. Perhaps a simpler way than checking if variables are undefined is to initialize them to a default boolean value (e.g. false), as is done in the example below. Try toggling the checkboxes:

angular.module('app', [])
  .controller('cont', function($scope) {
    $scope.country = 'ireland';
    $scope.name = 'Joe';
    $scope.settings = {
      eur: true,
      leak: false,
      usa: false
    };
    $scope.shouldShowLargerComplexContainer = function() {
      if (($scope.settings.leak == false && $scope.settings.eur == false && $scope.settings.usa == false)) {
        return true;
      }
      return false;
    };
  });
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="cont">
  country? name?
  <div ng-if="(country=='ireland' || country=='united kingdom') || (name=='John' || name=='Joe')">country Ireland and name is joe or john</div>
  Complex logic div?
  <div ng-if="shouldShowLargerComplexContainer()">larger complex div</div>
  <div>
    <input type="checkbox" ng-model="settings.eur" />eur</div>
  <div>
    <input type="checkbox" ng-model="settings.leak" />leak</div>
  <div>
    <input type="checkbox" ng-model="settings.usa" />usa</div>
</div>

Upvotes: 5

Shiny
Shiny

Reputation: 105

I found what I was doing incorrectly.
With if tags, your expression can use Ternary Operators and () Unsure what its called.

For example:
country == Ireland && (firstname == John || lastname == Doe) && console == PC

Which means:
If the country is Ireland AND firstname is john OR lastname is Doe AND console is PC then return true.

And where it was going wrong is the (). You need to put == true after the closing bracket for it to actually work.
This allowed me to do many expressions/conditions in one ng-if.

Final Code (This is an example of what I was doing with it):

ng-if="
settings.eur == true && settings.usa == false && settings.leak == false && (title.usa != undefined || title.rf != undefined || title.leak != undefined) == true ||
settings.usa == true && settings.eur == false && settings.leak == false && (title.eur != undefined || title.rf != undefined || title.leak != undefined) == true ||
settings.leak == true && settings.eur == false && settings.usa == false && (title.eur != undefined || title.usa != undefined || title.rf != undefined) == true ||

settings.eur == true && settings.usa == true && settings.leak == true && (title.usa != undefined && title.eur != undefined || title.rf != undefined) == true ||
settings.eur == true && settings.usa == true && settings.leak == false && (title.usa != undefined && title.eur != undefined || title.leak != undefined || title.rf != undefined) == true ||
settings.eur == true && settings.usa == false && settings.leak == true && (title.usa != undefined || title.rf != undefined) == true ||
settings.eur == false && settings.usa == true && settings.leak == true && (title.eur != undefined || title.rf != undefined) == true ||

settings.leak == false && settings.eur == false && settings.usa == false
"

Upvotes: 1

busy
busy

Reputation: 369

Angular 1.5.9+ does not allow to put conditions into expressions. Or there is a new magick way of doing it. Please confirm if I not wrong as I might be missing something.

ng-if="!item.title" - is not valid anymore as ! or others are not invalid charaters. like:

https://docs.angularjs.org/error/$parse/lexerr?p0=Unexpected%20nextharacter&p1=s13-13%20%5B%3D%5D&p2=item.title%3Dfalse

In changelog (https://github.com/angular/angular.js/blob/master/CHANGELOG.md ) it is called: improve performance of assignment expressions ?

https://docs.angularjs.org/guide/expression

No Control Flow Statements: You cannot use the following in an Angular expression: conditionals, loops, or exceptions.

The only solution I see is to move expressions into controller, but I do not know how to do it yet, I have multiple loops in template. Best not to upgrade angular.

Upvotes: 0

Andoni
Andoni

Reputation: 171

The Sam's response is ok, anyway looking at this with a wider perspective you should think again about if this decision should be taken in the view level or in the controller.

As a general rule try to not put any logic inside the view to avoid split the logic and increase the maintenance cost of property. (also is easier to test the logic inside the JS part)

Upvotes: 1

Related Questions