Search code examples
javascriptangularjsangular-ng-if

Angular check for one or more ng-if statements are true


I have a situation where I am building a dynamic table where cells contain an aggregate of data using several ng-if statements. Basically I need to know if none of the if statements are true so I can do another ng-if.

This is a simplified example of what I am doing. There are about 20 columns with different aggregated results.

<table>
    <tr ng-repeat="record in data">
        <td>
            <span ng-if="record.some_number > 0 && record.type == 'SomeType'">{{data1}}</span>
            <span ng-if="record.age >= 20 && record.age <= 50 && record.gender == 'MALE'">{{data2}}</span>
            <span ng-if="(record.age <= 20 || record.age >= 50) && record.gender == 'FEMALE'">{{data3}}</span>
            <span ng-if="!(record.some_number > 0 && record.type == 'SomeType') && !(record.age >= 20 && record.age <= 50 && record.gender == 'MALE') && !((record.age <= 20 || record.age <= 50) && record.gender == 'FEMALE')">{{data4}}</span>
        </td>
    </tr>
<table>

I can't use a ng-switch because the conditions are completely different. This is an aggregate of data, not if/else. I prefer a different approach to just adding a '!' to each condition in another span because some of my aggregates contain many conditions and some of the if statements are not trivial. There are also many aggregate cells so maintenance on the overly complicated 'else' conditions would be a nightmare.

Ideally I would love to just be able to assign a single variable to true on any ng-if statement being true. Any thoughts?


Solution

  • I don't know about it being a best practice, but I believe you should have all your logic in your JS, and the HTML should just be a template which reflects the state of the scope you're displaying.

    In this manner, your conditions would ALWAYS be checked in your JS.

    UPDATE: based on new content:

    So you have data and what it looks like is you need to process it first, else your app performance will suffer with an overload of watchers.

    First: simplify your HTML, all the logic like record.some_number > 0 && record.type == 'SomeType'" belongs in the JS.

    <table>
        <tr ng-repeat="record in data"> 
            <td>
                <span ng-repeat="item in record.dataToShow" ng-bind-html='item'></span> // now you just repeat the data that has been processed
            </td>
        </tr>
    </table>
    

    Second: do the processing in your JavaScript in a loop.

    $scope.data = [ some array with lots of stuff ];
    
    for( var idx in $scope.data ){
        var record = $scope.data[ idx ]; // assuming JSON object
        var dataToShow = []; // store your data(s) in an array
    
        // if a condition is met, push your data onto the array
        if( record.some_number > 0 && record.type == 'SomeType' ){
            dataToShow.push( data1 );
        }
        if( record.age >= 20 && record.age <= 50 && record.gender == 'MALE' ){
            dataToShow.push( data2 );
        }
        // continue processing conditions
    
        if( dataToShow.length === 0 ){ // none have been true if array is empty
            // do something
        }
        record.dataToShow = dataToShow;
    }
    

    https://plnkr.co/edit/ZPbui4rLwGGVVD4B90b9?p=preview