Customize cells elements in React Pivotview component

13 Sep 202524 minutes to read

You can customize each cell in the Pivot Table by using the cellTemplate property. The cellTemplate option accepts either an HTML string or the ID of an HTML element. You can use this to append extra HTML and show custom content or styles for every cell.

Implementation example

The following example demonstrates how to customize pivot table cells by displaying revenue trends with visual indicators. Each cell shows the actual value along with trend icons that represent performance direction.

import { PivotViewComponent } from '@syncfusion/ej2-react-pivotview';
import * as React from 'react';
import { renewableEnergy } from './datasource';
function App() {
    function cellTemplate(props) {
        return (<span className="tempwrap e-pivot-trend-neutral pv-icons"></span>);
    }
    let dataSourceSettings = {
        dataSource: renewableEnergy,
        expandAll: true,
        enableSorting: true,
        drilledMembers: [{ name: 'Year', items: ['FY 2015', 'FY 2017', 'FY 2018'] }],
        formatSettings: [{ name: 'ProCost', format: 'C0' }],
        rows: [
            { name: 'Year', caption: 'Production Year' }
        ],
        columns: [
            { name: 'EnerType', caption: 'Energy Type' },
            { name: 'EneSource', caption: 'Energy Source' }
        ],
        values: [
            { name: 'ProCost', caption: 'Revenue Growth' }
        ],
        filters: []
    };
    let pivotObj;
    return (<PivotViewComponent ref={d => pivotObj = d} id='PivotView' height={350} dataSourceSettings={dataSourceSettings} cellTemplate={cellTemplate.bind(this)} dataBound={trend.bind(this)}></PivotViewComponent>);
    function trend() {
        let cTable = [].slice.call(document.getElementsByClassName("e-table"));
        let colLen = pivotObj.pivotValues[3].length;
        let cLen = cTable[3].children[0].children.length;
        let rLen = cTable[3].children[1].children.length;
        let rowIndx;
        for (let k = 0; k < rLen; k++) {
            if (pivotObj.pivotValues[k] && pivotObj.pivotValues[k][0] !== undefined) {
                rowIndx = (pivotObj.pivotValues[k][0]).rowIndex;
                break;
            }
        }
        let rowHeaders = [].slice.call(cTable[2].children[1].querySelectorAll('td'));
        let rows = pivotObj.dataSourceSettings.rows;
        if (rowHeaders.length > 1) {
            for (let i = 0, Cnt = rows; i < Cnt.length; i++) {
                let fields = {};
                let fieldHeaders = [];
                for (let j = 0, Lnt = rowHeaders; j < Lnt.length; j++) {
                    let header = rowHeaders[j];
                    if (header.className.indexOf('e-gtot') === -1 && header.className.indexOf('e-rowsheader') > -1 && header.getAttribute('fieldname') === rows[i].name) {
                        var headerName = rowHeaders[j].getAttribute('fieldname') + '_' + rowHeaders[j].textContent;
                        fields[rowHeaders[j].textContent] = j;
                        fieldHeaders.push(rowHeaders[j].textContent);
                    }
                }
                if (i === 0) {
                    for (let rnt = 0, Lnt = fieldHeaders; rnt < Lnt.length; rnt++) {
                        if (rnt !== 0) {
                            let row = fields[fieldHeaders[rnt]];
                            let prevRow = fields[fieldHeaders[rnt - 1]];
                            for (let j = 0, ci = 1; j < cLen && ci < colLen; j++, ci++) {
                                let node = cTable[3].children[1].children[row].childNodes[j];
                                let prevNode = cTable[3].children[1].children[prevRow].childNodes[j];
                                let ri = undefined;
                                let prevRi = undefined;
                                if (node) {
                                    ri = node.getAttribute("index");
                                }
                                if (prevNode) {
                                    prevRi = prevNode.getAttribute("index");
                                }
                                if (ri && ri < [].slice.call(pivotObj.pivotValues).length) {
                                    if (pivotObj.pivotValues[prevRi][ci].value > pivotObj.pivotValues[ri][ci].value &&
                                        node.querySelector('.tempwrap')) {
                                        let trendElement = node.querySelector('.tempwrap');
                                        trendElement.className = trendElement.className.replace('sb-icon-neutral', 'sb-icon-loss');
                                    }
                                    else if (pivotObj.pivotValues[prevRi][ci].value < pivotObj.pivotValues[ri][ci].value &&
                                        node.querySelector('.tempwrap')) {
                                        let trendElement = node.querySelector('.tempwrap');
                                        trendElement.className = trendElement.className.replace('sb-icon-neutral', 'sb-icon-profit');
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
};
export default App;
import { IDataSet, Inject, PivotViewComponent } from '@syncfusion/ej2-react-pivotview';
import { DataSourceSettingsModel } from '@syncfusion/ej2-pivotview/src/model/datasourcesettings-model';
import * as React from 'react';
import { renewableEnergy } from './datasource';

function App() {

  function cellTemplate(props): JSX.Element {
    return (<span className="tempwrap e-pivot-trend-neutral pv-icons"></span>);
  }

  let dataSourceSettings: DataSourceSettingsModel = {
    dataSource: renewableEnergy as IDataSet[],
    expandAll: true,
    enableSorting: true,
    drilledMembers: [{ name: 'Year', items: ['FY 2015', 'FY 2017', 'FY 2018'] }],
    formatSettings: [{ name: 'ProCost', format: 'C0' }],
    rows: [
        { name: 'Year', caption: 'Production Year' }
    ],
    columns: [
        { name: 'EnerType', caption: 'Energy Type' },
        { name: 'EneSource', caption: 'Energy Source' }
    ],
    values: [
        { name: 'ProCost', caption: 'Revenue Growth' }
    ],
    filters: []
  }
  let pivotObj: PivotViewComponent;
  
    return (<PivotViewComponent  ref={ (d: PivotViewComponent) => pivotObj = d } id='PivotView' height={350} dataSourceSettings={dataSourceSettings} cellTemplate={cellTemplate.bind(this)} dataBound={trend.bind(this)}></PivotViewComponent>);

    function trend(): void {
        let cTable: HTMLElement[] = [].slice.call(document.getElementsByClassName("e-table"));
        let colLen: number = pivotObj.pivotValues[3].length;
        let cLen: number = cTable[3].children[0].children.length;
        let rLen: number = cTable[3].children[1].children.length;
        let rowIndx: number;

        for (let k: number = 0; k < rLen; k++) {
            if (pivotObj.pivotValues[k] && pivotObj.pivotValues[k][0] !== undefined) {
                rowIndx = ((pivotObj.pivotValues[k][0]) as IAxisSet).rowIndex;
                break;
            }
        }
        let rowHeaders: HTMLElement[] = [].slice.call(cTable[2].children[1].querySelectorAll('td'));
        let rows: IFieldOptions[] = pivotObj.dataSourceSettings.rows as IFieldOptions[];
        if (rowHeaders.length > 1) {
            for (let i: number = 0, Cnt = rows; i < Cnt.length; i++) {
                let fields: any = {};
                let fieldHeaders: any = [];
                for (let j: number = 0, Lnt = rowHeaders; j < Lnt.length; j++) {
                    let header: any = rowHeaders[j];
                    if (header.className.indexOf('e-gtot') === -1 && header.className.indexOf('e-rowsheader') > -1 && header.getAttribute('fieldname') === rows[i].name) {
                        var headerName = rowHeaders[j].getAttribute('fieldname') + '_' + rowHeaders[j].textContent;
                        fields[rowHeaders[j].textContent] = j;
                        fieldHeaders.push(rowHeaders[j].textContent);
                    }
                }
                if (i === 0) {
                    for (let rnt: number = 0, Lnt = fieldHeaders; rnt < Lnt.length; rnt++) {
                        if (rnt !== 0) {
                            let row: number = fields[fieldHeaders[rnt]];
                            let prevRow: number = fields[fieldHeaders[rnt - 1]];
                            for (let j: number = 0, ci = 1; j < cLen && ci < colLen; j++ , ci++) {
                                let node: HTMLElement = cTable[3].children[1].children[row].childNodes[j] as HTMLElement;
                                let prevNode: HTMLElement = cTable[3].children[1].children[prevRow].childNodes[j] as HTMLElement;
                                let ri: any = undefined;
                                let prevRi: any = undefined;
                                if (node) {
                                    ri = node.getAttribute("index");
                                }
                                if (prevNode) {
                                    prevRi = prevNode.getAttribute("index");
                                }
                                if (ri && ri < [].slice.call(pivotObj.pivotValues).length) {
                                    if ((pivotObj.pivotValues[prevRi][ci] as IAxisSet).value > (pivotObj.pivotValues[ri][ci]  as IAxisSet).value &&
                                     node.querySelector('.tempwrap')) {
                                        let trendElement: HTMLElement = node.querySelector('.tempwrap');
                                        trendElement.className = trendElement.className.replace('sb-icon-neutral', 'sb-icon-loss');
                                    } else if ((pivotObj.pivotValues[prevRi][ci]  as IAxisSet).value < (pivotObj.pivotValues[ri][ci]  as IAxisSet).value &&
                                     node.querySelector('.tempwrap')) {
                                        let trendElement: HTMLElement = node.querySelector('.tempwrap');
                                        trendElement.className = trendElement.className.replace('sb-icon-neutral', 'sb-icon-profit');
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
};

export default App;