Conditional groupBy in ng-repeat

How can one apply conditional grouping in an Angular ng-repeat directive?

For example, in the below code, I want to groupBy:'var1', but only when some variable, or expression, dontGroup evaluates to true. I don't want to have the bottom tr row duplicated specifically for the dontGroup variable in my HTML because the information cannot be loaded in via a template for a second tr due to the main table being controlled by a directive and needing the template in the DOM before initialization. If there's a way to do this that I'm overlooking, please let me know. I'm utilizing ng-table.

<table>
    <tr ng-repeat-start="(key, data) in $data | groupBy:'var1'">
        <td ng-bind="key">
            <!-- Grouped header info here. -->
        </td>
    </tr>
    <tr ng-repeat-end ng-repeat="item in data"> <!-- Repeat $data when `dontGroup` evaluates to true, 
                                                     otherwise repeat pre-grouped data from the `groupBy` filter above -->
        <td ng-bind="item.var2">
            <!-- Individual item info here. -->
        </td>
    </tr>
</table>

So, I want the lower ng-repeat function to repeat $data as data only when dontGroup evaluates to true, but otherwise I want $data to be run through the groupBy filter such that the data can have a header for the group.

I also cannot just drop an ng-if on the header row when dontGroup evaluates to true because I need the data to sort by other variables such as var2, var3, etc, and not have the var1 grouping affect that.

A fiddle for you to play with showing both wanted functionalities.


ANSWERS:


You can set the groupBy to reference a function and in the controller you can do a custom groupBy that will check for an indicator of how to group. Please see the following docs for more information.

Here is a rough attempt which should show the concept.

//template
<input type="checkbox" ng-click="clickGroupBY()"/>
  <table>
        <tr ng-repeat-start="(key, data) in $data | groupBy:valueGroupBY">

//controller
$scope.willgroupby = true;
$scope.valueGroupBY = function(group) {
if($scope.willgroupby) {
    return group.var1
}

return group.var2
}
$scope.clickGroupBY = function clickGroupBY() {
    $scope.willgroupby = !$scope.willgroupby;
}

UPDATE

I ran with the solution you came back with here and cleaned it up. see the following:

I also found this to be informative about the filters you are using:


Here I'm setting a conditional on the header row and returning a dummy object when dontGroup evaluates to true. It does mean, however, that var1 can't be equal to "test" in the grouped array, else the header won't be shown. "test" will just be a protected value.

Further, you could use this syntax with other filters when off of the grouping, as shown below.

<table>
    <tr ng-repeat-start="(key, data) in (dontGroup ? {'test': $data} : ($data | groupBy:'var1'))" ng-if="key != 'test'">
        <td ng-bind="key">

        </td>
    </tr>
    <tr ng-repeat-end ng-repeat="item in data | orderBy: 'var2')">
        <td ng-bind="item.var2">

        </td>
    </tr>
</table>

Fiddle

Check John Babb's answer for offloading some of this logic into the controller!



 MORE:


 ? dynamic ng-model using multiple dropdown and ng-reapeat
 ? Problems with fetching data from nested ng-repeat
 ? Using ng-repeat with ui-grid
 ? How do I code a toggle-able variable with a button in Python
 ? Raspberry Pi SSH connection over Ethernet fails
 ? Can't Call ScriptAlias Site Within Perl Script Within Apache
 ? angular2 listening for changes with Firebase
 ? Angular(2) - Running two projects with CLI
 ? Left alignment of <img> within a bootstrap grid system
 ? Hide table when search results 0