【问题标题】:Need to display total values in the footer in ag-grid using angular需要使用角度在 ag-grid 的页脚中显示总值
【发布时间】:2019-07-27 07:22:14
【问题描述】:

我目前正在我的 Angular 7 应用程序中实现 ag-grid。我需要为我已经实现的每个组添加页脚。我现在需要显示 EMV(USD) 的总计和百分比列,如下面的屏幕截图所示。除了提到的两列之外,每个单元格的行都应该是空白的,并且应该显示总数

组件

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;
    }
}

基于建议答案的新代码

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) + '%';
        }
    }

新截图

【问题讨论】:

  • 请停止分享截图,分享 plinkr\stackblitz 网址,每个人都可以测试你的方法

标签: angular ag-grid


【解决方案1】:

我以不同的方式做到了:

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

【讨论】:

    【解决方案2】:

    对于每个列定义,您可以传递一个额外的参数来更改列的呈现方式

    cellRenderer:'agGroupCellRenderer',
    cellRendererParams: {
        footerValueGetter: (params) => 'Text (' + params.value + ')'
    },
    aggFunc: "sum"
    

    其中 params.value 是列名

    【讨论】:

    • 我需要在哪里添加这个?在列定义 setgridOptions 方法。还有它如何知道必须为特定列添加总计
    • 应该在getColumns函数的定义数组中,看第二个问题的更新答案。
    • more details 关于分组页脚,但我想说@Tom,你必须查看pinned rows - 它比对齐网格(作为页脚)或footerValueGetter 要容易得多 -因为它还不够
    • 我确实在我的 getColumns 函数中尝试了上述方法,它显示 Text(0)
    • 网格是否有能力通过使用一些内置函数来汇总该列的行数
    【解决方案3】:

    Ag Grid 具有称为 groupIncludeFooter、groupIncludeTotalFooter 的属性。你可以参考https://www.ag-grid.com/javascript-grid-grouping/#grouping-footers

      <ag-grid-angular
          ...
          [groupIncludeFooter]="true"
          [groupIncludeTotalFooter]="true"
          ...
        ></ag-grid-angular>
    

    https://plnkr.co/edit/pBG3to7sebxDC7Yq

    希望对你有帮助:-)

    【讨论】:

    • 当没有应用分组时,我们如何在加载网格时应用 aggFunc 它,该行显示为空白。
    【解决方案4】:

    我早些时候发现了这个,您可以使用aligned grids as footer。他们包含了一个示例,因此您应该参考它。

    总结一下,在 component.html 中,您必须在模板中包含两次 ag-grid-angular 组件,每个组件都有自己的 gridOptions 属性

    <ag-grid-angular #topGrid [gridOptions]="topOptions"></ag-grid-angular>
    <ag-grid-angular #bottomGrid [gridOptions]="bottomOptions".... ></ag-grid-angular>
    

    在您的 component.ts 上,您将像往常一样定义您的 columnDefs,以及相应的 gridOptions

    如上面链接中的示例所述,对齐两个网格将为您提供一个与主网格垂直对齐的页脚网格。这样,您可以在该页脚上显示总值等。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-18
      • 1970-01-01
      • 2020-02-01
      • 2021-07-21
      • 1970-01-01
      • 2021-10-09
      • 2016-02-07
      • 2018-10-23
      相关资源
      最近更新 更多