Angularjs groupBy + orderBy

I am using groupBy from angular-filter to group an array of objects by their date property.

<div ng-repeat="(day, dayEvents) in events | groupBy: 'date' )">
 <h3>{{ day | date: mediumDate }}</h3>
</div>

Which produces the following:

Feb 9, 2015 
Feb 10, 2015 
Feb 11, 2015 
Feb 12, 2015 

How can I reverse the order to start from the most recent date? When I print to the console the array is printed with the order I want:

  Object {
     1423699200000: Array[1],
     1423612800000: Array[7],
     1423526400000: Array[11],
     1423440000000: Array[1]
 }

I also wrote a custom filter to reverse the order after the groupBy:

.filter("reverseOrder", function() {
        function sortNumber(a,b) {
            return  parseInt(b) - parseInt(a);
        }
        return function(collection) {
            var keys = Object.keys(collection).sort(sortNumber);
            var reveredCollection= {};
            var length=collection.length;
            angular.forEach(keys, function(key) {
                reveredCollection[key] = collection[key];
            });
           return reveredCollection;
        }
    })

Which I have applied like this:

<div ng-repeat="(day, dayEvents) in events | groupBy: 'date' | reverseOrder )">
     <h3>{{ day | date: mediumDate }}</h3>
</div>

Answers:

Answer

Recently had the same issue. groupBy creates an object, but the orderBy needs an array, so there's a little bit of funkiness involved. I ended up getting the answer straight from their issues page where one of the authors does an excellent job of explaining it complete with code samples that was basically copy/paste for me.

https://github.com/a8m/angular-filter/issues/57#issuecomment-65041792

Answer

It appears the proper method is to use the | toArray: true | orderBy: customMappingFunction, however, I found the performance on this to be terrible. I came up with a solution that keeps performance up and produces the correct result -- (although it does seem a bit odd!)

<div ng-repeat="(key, results) in allResults | groupBy: '-someKey' )">
    <h3>{{ key | ltrim: '-' }}</h3>
    <ul>
        <li ng-repeat="result in results">
            {{ result }}
        </li>
    </ul>
</div>

For whatever reason, adding the - does force the groupBy to sort correctly, but it also adds it to the key, so we can just remove it!

Answer

We can achieve this by ordering the data in controller & converting groupBy output to Array.

In controller, order the records before sending it to view :

$scope.events = $filter('orderBy')(events, '-date');

Now the template, receives data in sorted order. After grouping, we need to transform it to Array :

<div ng-repeat="(day, dayEvents) in events | groupBy: 'date' | toArray:true )">
     <h3>{{ day | dayEvents[0].date: mediumDate }}</h3>
</div>
Answer

An easier way to reverse an array is to use the code from this answer

app.filter('reverseOrder', function() {
  return function(items) {
    return items.slice().reverse();
  };
});

<div ng-repeat="(day, dayEvents) in events | groupBy: 'date' | reverseOrder )">
     <h3>{{ day | date: mediumDate }}</h3>
</div>
Answer

try using -

<div ng-repeat="(day, dayEvents) in events | groupBy: '-date' ">

P.S- I have not used groupBy till now anywhere!But this minus thing works well with orderBy attribute!

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.