1

Similar to this related question, I want to group an array of objects, e.g., by team name

[
 {name: 'Gene', team: 'team alpha'},
 {name: 'George', team: 'team beta'},
 {name: 'Steve', team: 'team gamma'},
 {name: 'Paula', team: 'team beta'},
 {name: 'Scruath of the 5th sector', team: 'team gamma'}
];

Unfortunately, the accepted answer using ng-repeat with a groupBy filter doesn't seem to work within an Angular Material expansion panel, which is what I'm trying to do: I want multiple expansion panels, one per team, which, when expanded, show the involved players.

I tried

<mat-expansion-panel ng-repeat="(key, value) in players | groupBy: 'team'">
    <mat-expansion-panel-header>
      <mat-panel-title>{{ key }}</mat-panel-title>
    </mat-expansion-panel-header>
    <li ng-repeat="player in value">
      {{player.name}}
    </li>
</mat-expansion-panel>

However, ng-repeatis not allowed inside the mat-expansion-panel. *ngFor is allowed but I don't know how to use it with the groupBy filter. *ngFor="let player in players | groupBy: 'team'" throws an error and I can't find any documentation.

sanduniYW
  • 723
  • 11
  • 19
stefanbschneider
  • 5,460
  • 8
  • 50
  • 88

1 Answers1

4

You should make your own custom pipe to support GroupBy, also ng-repeat is an angularjs syntax, you should use ngFor.

Your custom pipe should look as,

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'groupBy'})
export class GroupByPipe implements PipeTransform {
    transform(collection: Array<any>, property: string): Array<any> {
         if(!collection) {
            return null;
        }

        const groupedCollection = collection.reduce((previous, current)=> {
            if(!previous[current[property]]) {
                previous[current[property]] = [current];
            } else {
                previous[current[property]].push(current);
            }

            return previous;
        }, {});

        return Object.keys(groupedCollection).map(key => ({ key, value: groupedCollection[key] }));
    }
}

STACKBLITZ DEMO

Sajeetharan
  • 216,225
  • 63
  • 350
  • 396
  • Why would they remove functionality from AngularJS? I'd expect many people could benefit from a built-in "groupBy" pipe. – stefanbschneider Sep 03 '18 at 18:10
  • Follow up question: What if I'm trying to group by date, but not exact date (with time) only really year, month, day? I tried chaining pipes but it didn't work. I would probably have to drop the hour, minute, second, millisecond before, right? – stefanbschneider Sep 03 '18 at 18:41