J'implémente actuellement ag-grid dans mon angular 7. J'ai besoin d'inclure le pied de page pour chaque groupe que j'ai atteint. Il me faudrait maintenant afficher le total d'EMV (USD) et Colonne de pourcentage comme la capture d'écran ci-dessous. La ligne doit être vide pour chaque cellule, à l'exception des deux colonnes mentionnées et les totaux doivent être affichés
Composant
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;
}
}
Nouveau code basé sur la réponse proposée
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) + '%';
}
}
Nouvelle capture d'écran
Je l'ai fait d'une manière différente:
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;
}
J'ai trouvé cela plus tôt, grâce auquel vous pouvez utiliser grilles alignées en pied de page . Ils ont inclus un exemple, vous devriez donc vous y référer.
Un résumé, sur le component.html, vous devez inclure le ag-grid-angular
composant deux fois sur votre modèle, chacun avec ses propres propriétés gridOptions
<ag-grid-angular #topGrid [gridOptions]="topOptions"></ag-grid-angular>
<ag-grid-angular #bottomGrid [gridOptions]="bottomOptions".... ></ag-grid-angular>
Et sur votre component.ts, vous définirez votre columnDefs
comme d'habitude, ainsi que les gridOptions
respectifs.
Comme mentionné dans l'exemple sur le lien ci-dessus, l'alignement des deux grilles vous donnera une grille de pied de page qui est alignée verticalement sur votre grille principale. De cette façon, vous pouvez afficher la valeur totale, etc. sur ce pied de page.
Pour chaque définition de colonne, vous pouvez passer un paramètre supplémentaire pour modifier le rendu de la colonne
cellRenderer:'agGroupCellRenderer',
cellRendererParams: {
footerValueGetter: (params) => 'Text (' + params.value + ')'
},
aggFunc: "sum"
où params.value est le nom de la colonne