0

Simplified from this ag-grid example. See code comments. I can attach a custom cellRenderer for rowGroup rows. But all my attempts at a custom cellRenderer for leaf node rows have broken the row grouping functionality. Seems we can differentiate leaf vs group nodes via existence of params.data. If I put a cellRenderer in the autoGroupColumnDef, bad things happen: I lose all group row functionality. If I test for params.data in that cellRenderer, I don't know what to return if it's not a leaf node. I've tried several angles on 'agGroupCellRenderer', none correct. Thank you.

'use strict';

import React, { useCallback, useMemo, useRef, useState } from 'react';
import { render } from 'react-dom';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-enterprise';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: '100%', height: '100%' }), []);
  const gridStyle = useMemo(() => ({ height: '100%', width: '100%' }), []);
  const [rowData, setRowData] = useState();
  const [columnDefs, setColumnDefs] = useState([
    { field: 'country', rowGroup: true, hide: true }
    /*  I've whittled things down to only 1-deep leaf rows, and the auto-generated group rows.
      { field: 'sport', rowGroup: true, hide: true },
      { field: 'gold', aggFunc: 'sum' },
      { field: 'silver', aggFunc: 'sum' },
      { field: 'bronze', aggFunc: 'sum' },
      { field: 'age', minWidth: 120, checkboxSelection: true, aggFunc: 'sum' },
      { field: 'year', maxWidth: 120 },
      { field: 'date', minWidth: 150 },
    */
  ]);
  const defaultColDef = useMemo(() => {
    return {
      flex: 1,
      minWidth: 100,
      // New: added cellRenderer. Seems to apply only to rowGroup rows
      cellRenderer: params => {
        return 'groupRow cellRenderer: ' + params.value;
      }
    };
  }, []);
  const autoGroupColumnDef = useMemo(() => {
    return {
      headerName: 'Athlete',
      field: 'athlete',
      minWidth: 250,
      cellRenderer: 'agGroupCellRenderer',
      cellRendererParams: {
        checkbox: true,
      },
    };
  }, []);

  // Now want to add a cellRenderer that applies ONLY to leaf nodes.
  // Seems we can differentiate leaf vs group nodes via existence of params.data.
  // If I put a cellRenderer in the above autoGroupColumnDef, bad things happen:
  // I lose all group row functionality. If I test for params.data in that cellRenderer, I don't know
  // what to return if it's not a leaf node. I've tried several angles on 'agGroupCellRenderer', none correct.

  const gridRef = useRef();
  const [gridApi, setGridApi] = useState(null);
  const onGridReady = useCallback((params) => {
    fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
      .then((resp) => resp.json())
      .then((data) => setRowData(data));
    // Added: grab a gridRef reference
    gridRef.current = document.querySelector('#theGrid');  
    // Added: grab the api instance
    setGridApi(params.api);
  }, []);

  return (
    <div style={containerStyle}>
      <div id="theGrid" style={gridStyle} className="ag-theme-alpine">
        <AgGridReact
          rowData={rowData}
          columnDefs={columnDefs}
          defaultColDef={defaultColDef}
          autoGroupColumnDef={autoGroupColumnDef}
          rowSelection={'multiple'}
          groupSelectsChildren={true}
          suppressRowClickSelection={true}
          suppressAggFuncInHeader={true}
          onGridReady={onGridReady}
        ></AgGridReact>
      </div>
    </div>
  );
};

render(<GridExample></GridExample>, document.querySelector('#root'));

1 Answers1

0

Well, I was able to sidestep the issue, by employing an innerRenderer in the autoGroupColumnDef, which gets applied to all nodes, both group and leaf. Even so, would still like to know how to directly invoke the default 'agGroupCellRenderer' other than declaratively via cellRenderer: 'agGroupCellRenderer' (how to invoke it from a cellRendererSelector, for example).
Here's a corrected version with functional innerRenderer:

'use strict';

import React, { useCallback, useMemo, useRef, useState } from 'react';
import { render } from 'react-dom';
import { AgGridReact } from 'ag-grid-react';
import 'ag-grid-enterprise';
import 'ag-grid-community/styles/ag-grid.css';
import 'ag-grid-community/styles/ag-theme-alpine.css';

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: '100%', height: '100%' }), []);
  const gridStyle = useMemo(() => ({ height: '100%', width: '100%' }), []);
  const [rowData, setRowData] = useState();
  const [columnDefs, setColumnDefs] = useState([
    { field: 'country', rowGroup: true, hide: true }
    /*  I've whittled things down to only 1-deep leaf rows, and the auto-generated group rows.
      { field: 'sport', rowGroup: true, hide: true },
      { field: 'gold', aggFunc: 'sum' },
      { field: 'silver', aggFunc: 'sum' },
      { field: 'bronze', aggFunc: 'sum' },
      { field: 'age', minWidth: 120, checkboxSelection: true, aggFunc: 'sum' },
      { field: 'year', maxWidth: 120 },
      { field: 'date', minWidth: 150 },
    */
  ]);
  const defaultColDef = useMemo(() => {
    return {
      flex: 1,
      minWidth: 100,
    };
  }, []);
  const autoGroupColumnDef = useMemo(() => {
    return {
      headerName: 'Athlete',
      field: 'athlete',
      minWidth: 250,
      cellRenderer: 'agGroupCellRenderer',
      cellRendererParams: {
        checkbox: true,        
        // Declare the new innerRenderer:
        innerRenderer: SimpleCellRenderer,
      },
    };
  }, []);

  // Slight modification of Ag's example
  function SimpleCellRenderer (props) 
  { 
    return (
        <span
          style={{
            // This differentiates based on node level ('0' for group nodes, '1' for leaf nodes)
            backgroundColor: props.node.level ? 'coral' : 'lightgreen',
            padding: 2,
          }}
        >
          {props.value}
        </span>
    )
  };

  const gridRef = useRef();
  const [gridApi, setGridApi] = useState(null);
  const onGridReady = useCallback((params) => {
    fetch('https://www.ag-grid.com/example-assets/olympic-winners.json')
      .then((resp) => resp.json())
      .then((data) => setRowData(data));
    // Added: grab a gridRef reference
    gridRef.current = document.querySelector('#theGrid');  
    // Added: grab the api instance
    setGridApi(params.api);
  }, []);

  return (
    <div style={containerStyle}>
      <div id="theGrid" style={gridStyle} className="ag-theme-alpine">
        <AgGridReact
          rowData={rowData}
          columnDefs={columnDefs}
          defaultColDef={defaultColDef}
          autoGroupColumnDef={autoGroupColumnDef}
          rowSelection={'multiple'}
          groupSelectsChildren={true}
          suppressRowClickSelection={true}
          suppressAggFuncInHeader={true}
          onGridReady={onGridReady}
        ></AgGridReact>
      </div>
    </div>
  );
};

render(<GridExample></GridExample>, document.querySelector('#root'));