Search code examples
javascriptag-gridjsgridag-grid-validation

AG-Grid: Column Grouping based on children set


I have an ag-grid columnDef similar to this structure.

gridOptions.columnDefs = [
    {
        headerName: 'Athlete Details',
        children: [
            { headerName: 'Name', field: 'name' },
            { headerName: 'Age', field: 'age' },
            { headerName: 'Country', field: 'country' }
        ]
    },
    {
        headerName: 'Sports Results',
        children: [
            { headerName: 'Sport', field: 'sport' },
            { headerName: 'Total', columnGroupShow: 'closed' },
            { headerName: 'Gold', columnGroupShow: 'open' },
            { headerName: 'Silver', columnGroupShow: 'open' },
            { headerName: 'Bronze', columnGroupShow: 'open' }
        ]
    }
];

With this kind of data set, is it possible to group both sets using the name of the athlete?

I want to create a group that displays only the name of the Athlete with a count of total number of medals, and the Name item on the grid is expandable/collapsible which looks something like this.

enter image description here


Solution

  • When you segregate the columns into column groups, it is just a way of displaying the data but behind the scenes, that data is not disjoint but one chunk of array. So you can group any number of column groups by any one row. In this case 'Athlete'.

    To achieve the result you want, a few tweaks to gridOptions and colDefs are required. I will post the relevant code with comments inline.

    In template -

      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [autoGroupColumnDef]="autoGroupColumnDef" // to customize your grouped column
      [suppressAggFuncInHeader]="true" // to suppress column headers with aggregate function prefix like sum(Gold)
    

    In component -

     constructor(private http: HttpClient) {
         this.columnDefs = [
          {
            headerName: 'Athlete Details',
            children: [
              {
                headerName: 'Athlete',
                field: 'athlete',
                width: 180,
                filter: 'agTextColumnFilter',
                rowGroup: true, // this to group by athlete
                hide: true // hide this column as you will display grouped column
              },
              {
                headerName: 'Age',
                field: 'age',
                width: 90,
                filter: 'agNumberColumnFilter',
              },
              {
                headerName: 'Country',
                field: 'country',
                width: 140,
              },
            ],
          },
          {
            headerName: 'Sports Results',
            children: [
              {
                headerName: 'Sport',
                field: 'sport',
                width: 140,
              },
    
              {
                headerName: 'Gold',
                field: 'gold',
                width: 100,
                filter: 'agNumberColumnFilter',
                 aggFunc: 'sum' // to show subtotals at group level for this column
              },
              {
                headerName: 'Silver',
                field: 'silver',
                width: 100,
                filter: 'agNumberColumnFilter',
                 aggFunc: 'sum'
              },
              {
                headerName: 'Bronze',
                field: 'bronze',
                width: 100,
                filter: 'agNumberColumnFilter',
                 aggFunc: 'sum'
              },
              {
                headerName: 'Total',
                field: 'total',
                width: 100,
                filter: 'agNumberColumnFilter',
                 aggFunc: 'sum'
              },
            ],
          },
        ];
        this.defaultColDef = {
          flex: 1,
          minWidth: 100,
          filter: true,
          sortable: true,
          resizable: true,
        };
        this.autoGroupColumnDef = {
          headerName: 'Athlete', // naming your grouped column
          minWidth: 200,}
          }
    

    Here's how it looks enter image description here