title: Need to display total values in the footer in ag-grid using angular
body: <p>I am currently implementing ag-grid in my angular 7 application. I need to include the footer for each group which I have achieved. I would now need to display the Total of EMV(USD) and Percent Column like the screenshot below. The row should be blank for each cell except for the two columns mentioned and the totals should be displayed</p>
  
  <p><a href="https://i.stack.imgur.com/ORUaM.png" rel="noreferrer"><img src="https://i.stack.imgur.com/ORUaM.png" alt="enter image description here"></a></p>
  
  <p>Component</p>
  
  <pre><code>import { Component, Injectable, NgZone, ViewEncapsulation, ViewChild, Input } from '@angular/core';
  import { OnInit } from '@angular/core';
  import { AllocationsService } from '../services/allocations.service';
  import { formatDate } from '@angular/common';
  import { GridOptions } from 'ag-grid-community/dist/lib/entities/gridOptions';
  import { Comparator } from '../utilities/comparator';
  import { ActivatedRoute } from '@angular/router';
  import { TestBed } from '@angular/core/testing';
  
  
  @Component({
      selector: 'mgr-allocations',
      templateUrl: './allocations.component.html'
  })
  
  
  export class AllocationsComponent implements OnInit {
  
      private Error: string;
      public evalDate: Date;
      private _evalDate: Date;
      public AllocationDetails: any;
      private _ManagerStrategyId: number;
      public GridOptions: GridOptions;
      windowHeight: any;
      offset: number;
      ngZone: any;
      router: any;
      Comparator: Comparator;
      Route: any;
  
      public get ManagerStrategyId(): number {
          return this._ManagerStrategyId;
      }
  
  
      @Input()
      public set ManagerStrategyId(value: number) {
          this._ManagerStrategyId = value;
      }
  
  
      constructor(private allocationsService: AllocationsService, private comparator: Comparator,
                  private zone: NgZone, private route: ActivatedRoute) {
          this.Comparator = comparator;
          this.Route = route;
  
          window.onresize = (e) =&gt; {
              this.ngZone.run(() =&gt; {
                  this.windowHeight = window.innerHeight - this.offset;
                  setTimeout(() =&gt; {
                      if (!this.GridOptions || !this.GridOptions.api) {
                          return;
                      }
                      this.GridOptions.api.sizeColumnsToFit();
                  }, 500, true);
              });
          };
      }
  
      private FormattedDate(dateToFormat: Date): string {
          return formatDate(dateToFormat, 'yyyy/MM/dd', 'en');
      }
  
  
      get MissingProductKeys() {
          const  missingProductsTypesNames = this.AllocationDetails.MissingProducts.flat().map(({ProductType}) =&gt; ProductType);
          const  uniqueProductTypeNames = new Set(missingProductsTypesNames);
          return  Array.from(uniqueProductTypeNames.values());
      }
  
      setGridOptions() {
          this.GridOptions = {
              columnDefs: this.getColumns(),
              enableFilter: true,
               treeData: true,
              enableColResize: true,
              animateRows: true,
              groupDefaultExpanded: 1,
              enableSorting: true,
              suppressCellSelection: true,
              groupIncludeFooter: true,
              getDataPath: function (data) {
                  return data.Hierarchy;
              },
              onGridReady: e =&gt; {
                  if (!e || !e.api) {
                      return;
                  }
                  e.api.sizeColumnsToFit();
                  this.setDefaultSortOrder();
              },
              getRowStyle: (params) =&gt; {
                  if (params.node.level === 0) {
                      return { 'background-color': '#FCE7D7' };
                  }
              },
  
              autoGroupColumnDef: {
                  headerName: 'Manager Strategy', width: 300,
                  valueFormatter: uniqueColumn
              },
  
          };
          function uniqueColumn(params) {
  
          const startIndex = params.value.indexOf('#');
          if (startIndex === -1) { return params.value; }
  
          const endIndex = params.value.length;
          return params.value.replace(params.value.substring(startIndex, endIndex), '');
  
      }
      }
  
      ngOnInit() {
          this.evalDate = new Date();
          this.setGridOptions();
          this.getAllocationsDetails(this.FormattedDate(this.evalDate));
  
      }
  
       getAllocationsDetails(evalDate: string) {
          if (this.ManagerStrategyId != null) {
              this.initGrid();
             //this.GridOptions.api.showLoadingOverlay();
              this.allocationsService.getAllocationsDetails(this.ManagerStrategyId, evalDate)
                  .subscribe(data =&gt; {
                      this.AllocationDetails = data;
                      this.GridOptions.rowData = this.AllocationDetails.ManagerAllocations;
                      setTimeout(() =&gt; {
                        //  this.GridOptions.api.hideOverlay();
                      }, 100, true);
                  },
                      err =&gt; {
                          this.Error = 'An error has occurred. Please contact BSG';
                      },
                      () =&gt; {
                        //  this.GridOptions.api.hideOverlay();
                      });
          }
      }
  
  
      public evalDateChanged(value: Date): void {
          this.getAllocationsDetails(this.FormattedDate((value)));
      }
  
      GridHeight() {
          if (!this.windowHeight) {
              this.windowHeight = window.innerHeight - this.offset + 10;
          }
          return this.windowHeight;
      }
  
  
      setDefaultSortOrder() {
          const defaultSortModel = [
              { colId: 'ManagerStrategyName', sort: 'asc' },
              { colId: 'ManagerFundName', sort: 'asc' }
          ];
          this.GridOptions.api.setSortModel(defaultSortModel);
      }
  
      private initGrid() {
          const self = this;
      }
  
  
  
      private getColumns(): Array&lt;any&gt; {
          const self = this;
          const definition = [
              { headerName: 'Date', field: 'EvalDate', hide: true },
              { headerName: 'Firm ID', field: 'FirmID', hide: true },
              { headerName: 'Manager Strategy ID', field: 'FirmName', hide: true },
              { headerName: 'Firm', field: 'ManagerStrategyID', hide: true },
              { headerName: 'Manager Strategy', field: 'ManagerStrategyName' , hide: false },
              { headerName: 'Fund ID', field: 'ManagerFundID', hide: true },
              { headerName: 'Fund', field: 'ManagerFundName' },
              { headerName: 'Portfolio', field: 'ProductName' },
              { headerName: 'As Of', field: 'EvalDate',   cellRenderer: (data) =&gt; {
                  return data.value ? (new Date(data.value)).toLocaleDateString() : '';
               } },
              { headerName: 'EMV (USD)', field: 'UsdEmv',  valueFormatter: currencyFormatter },
              { headerName: 'Percent', field: 'GroupPercent', valueFormatter: formatPercent },
  
  
  
  
  
          ];
          function currencyFormatter(params) {
              if (!isNaN(params.value)) {
              return '$' + formatNumber(params.value);
              }
          }
  
          function formatNumber(number) {
              // this puts commas into the number eg 1000 goes to 1,000,
               return Math.floor(number).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
          }
  
          function formatPercent(number) {
              if (!isNaN(number.value)) {
              return (number.value * 100).toFixed(2) + '%';
              }
          }
          return definition;
      }
  }
  </code></pre>
  
  <p>New code based on proposed answer</p>
  
  <pre><code>private getColumns(): Array&lt;any&gt; {
          const self = this;
          const definition = [
              { headerName: 'Date', field: 'EvalDate', hide: true },
              { headerName: 'Firm ID', field: 'FirmID', hide: true },
              { headerName: 'Manager Strategy ID', field: 'FirmName', hide: true },
              { headerName: 'Firm', field: 'ManagerStrategyID', hide: true },
              { headerName: 'Manager Strategy', field: 'ManagerStrategyName', hide: false },
              { headerName: 'Fund ID', field: 'ManagerFundID', hide: true },
              { headerName: 'Fund', field: 'ManagerFundName' },
              { headerName: 'Portfolio', field: 'ProductName' },
              {
                  headerName: 'As Of', field: 'EvalDate', cellRenderer: (data) =&gt; {
                      return data.value ? (new Date(data.value)).toLocaleDateString() : '';
                  }
              },
              {
                  headerName: 'EMV (USD)', field: 'UsdEmv', valueFormatter: this.currencyFormatter,
                  cellRenderer: 'agGroupCellRenderer',
                  aggFunc: 'sum',
                  cellRendererParams: {
                      footerValueGetter: (params) =&gt;   params.value
  
                  }
              },
              {
                  headerName: 'Percent', field: 'GroupPercent', valueFormatter: this.formatPercent,
                  cellRenderer: 'agGroupCellRenderer',
                  aggFunc: 'sum',
                  cellRendererParams: {
                      footerValueGetter: (params) =&gt; params.value
                  }
              }
          ];
          return definition;
      }
  
  
      currencyFormatter(number) {
          // this puts commas into the number eg 1000 goes to 1,000,
          if (!isNaN(number.value)) {
          number = Math.floor(number.value).toString().replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
          number = number === '0' ? '0.00' : number;
          return '$' + number;
          }
      }
  
       formatPercent(number) {
          if (!isNaN(number.value)) {
              return (number.value * 100).toFixed(2) + '%';
          }
      }
  </code></pre>
  
  <p>New Screenshot</p>
  
  <p><a href="https://i.stack.imgur.com/WpmmB.png" rel="noreferrer"><img src="https://i.stack.imgur.com/WpmmB.png" alt="enter image description here"></a></p>