Search code examples
javascriptangularjsangularjs-ng-repeatangular-ng-if

Angular JS ng-if an ng-repeat complex match length is greater than given value?


I have an ng-repeat that shows a table based on one loop, and then a cell based on a different loop:

<tbody>
   <tr ng-repeat="r in roles | limitTo: 30">
     <td>{{r.name}}</td>
     <td>
        <span ng-repeat="t in users100 | limitTo: r.userLimit" ng-if="t.role == r.name"><a href="{{t.id}}">{{t.full_name}}</a></span> 
        <span ng-if="true"><a href="" ng-click="r.userLimit=500">Show all</a></span>
     </td>
   </tr>
 </tbody>

Each row is a Role, first cell shows the role's name.

Second cell shows all results from a different dataset where the role in that set matches the original set's role value. (It repeats a SPAN for each match up to r.userLimit, set in the JSON at 20)

The A tag has a click which sets the value of r.userLimit to 500, so it shows all the users.

My question is, I only want to show this link IF the number of matches to the initial repeater is greater than the value of r.userLimit (20)

So I thought

ng-if="((t.role == r.name).length > r.userLimit)"

But my syntax is wrong, since the link never shows. What's wrong wih my syntax?


Solution

  • You'd need to get 2 lengths: the original array and the filtered one:

    This is how you can do so with ng-repeat:

    <span ng-repeat="t in shownUsers = (users100 | limitTo: limit)">
    

    Or, even easier, with Angular 1.3:

    <span ng-repeat="t in users100 | limitTo: limit as shownUsers">
    

    Then, you use the two with ng-if for "show all". You also don't need to hack "all" with "a very high number":

    <span ng-show="shownUsers.length < users100.length" ng-click="limit = users100.length">
       Show All
    </span>
    

    As a bonus, this can also enable you to do "show more" quite easily:

    <span ng-show="shownUsers.length < users100.length" ng-click="limit = limit + 10">
       show more
    </span>
    

    EDIT: There is further complexity if the results are themselves filtered, then the as alias would not suffice. In this case, the following works (shortening variable names for readability):

    <span ng-repeat="t in shown = (filtered = (users | filter: {role: r.name}) | limitTo: limit)">
    

    and then, use shown.length against filtered.length:

    <span ng-show="shown.length < filtered.length" ng-click="limit = users.length">
       show all
    </span>