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
Component
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) => {
this.ngZone.run(() => {
this.windowHeight = window.innerHeight - this.offset;
setTimeout(() => {
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}) => 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 => {
if (!e || !e.api) {
return;
}
e.api.sizeColumnsToFit();
this.setDefaultSortOrder();
},
getRowStyle: (params) => {
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 => {
this.AllocationDetails = data;
this.GridOptions.rowData = this.AllocationDetails.ManagerAllocations;
setTimeout(() => {
// this.GridOptions.api.hideOverlay();
}, 100, true);
},
err => {
this.Error = 'An error has occurred. Please contact BSG';
},
() => {
// 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<any> {
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) => {
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;
}
}
New code based on proposed answer
private getColumns(): Array<any> {
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) => {
return data.value ? (new Date(data.value)).toLocaleDateString() : '';
}
},
{
headerName: 'EMV (USD)', field: 'UsdEmv', valueFormatter: this.currencyFormatter,
cellRenderer: 'agGroupCellRenderer',
aggFunc: 'sum',
cellRendererParams: {
footerValueGetter: (params) => params.value
}
},
{
headerName: 'Percent', field: 'GroupPercent', valueFormatter: this.formatPercent,
cellRenderer: 'agGroupCellRenderer',
aggFunc: 'sum',
cellRendererParams: {
footerValueGetter: (params) => 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) + '%';
}
}
New Screenshot
I've made it in a different way:
let pinnedBottomData = this.generatePinnedBottomData();
this.gridApi.setPinnedBottomRowData([pinnedBottomData]);
generatePinnedBottomData(){
// generate a row-data with null values
let result = {};
this.gridColumnApi.getAllGridColumns().forEach(item => {
result[item.colId] = null;
});
return this.calculatePinnedBottomData(result);
}
calculatePinnedBottomData(target:any){
//list of columns for aggregation
let columnsWithAggregation = ['age']
columnsWithAggregation.forEach(element => {
this.gridApi.forEachNodeAfterFilter((rowNode: RowNode) => {
if (rowNode.data[element])
target[element] += Number(rowNode.data[element].toFixed(2));
});
if (target[element])
target[element] = `Age Sum: ${target[element].toFixed(2)}`;
})
return target;
}
Demo
For each column definition, you can pass an extra parameter to change how the column is rendered
cellRenderer:'agGroupCellRenderer',
cellRendererParams: {
footerValueGetter: (params) => 'Text (' + params.value + ')'
},
aggFunc: "sum"
where params.value is the column name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With