Search code examples
ag-gridag-grid-angular

Can I set an ag-grid full-width row to have autoHeight?


I am trying to render a set of footnotes at the end of my data set. Each footnote should be a full-width row. On the docs page for row height, it says that you can set an autoHeight property for the column you want to use to set the height. Full-width rows, however, aren't tied to any column, so I don't think there's a place to set that autoHeight property.

For reference, here is my cell renderer, which gets invoked if a flag in the data object is true.

import { Component } from '@angular/core';
import { ICellRendererComp, ICellRendererParams } from '@ag-grid-community/core';

@Component({
  template: '',
})
export class FootnoteRendererComponent implements ICellRendererComp {
  cellContent: HTMLElement;

  init?(params: ICellRendererParams): void {
    this.cellContent = document.createElement('div');
    this.cellContent.innerHTML = params.data.title;
    this.cellContent.setAttribute('class', 'footnote');
  }

  getGui(): HTMLElement {
    return this.cellContent;
  }

  refresh(): boolean {
    return false;
  }
}

The footnote (the "title" property above) could be one line or several depending on its length and the browser's window size. There may also be several footnotes. Is there a way to set autoHeight for each footnote row? Thanks for any help!


Solution

  • Here is the solution I ended up with, though I like @LennyLip's answer as well. It uses some ideas from Text Wrapping in ag-Grid Column Headers & Cells.

    There were two parts to the problem - 1) calculating the height, and 2) knowing when to calculate the height.

    1) Calculating the Height

    I updated the footnote's Cell Renderer to add an ID to each footnote text node, and used it in the function below.

    const footnoteRowHeightSetter = function(params): void {
      const footnoteCells = document.querySelectorAll('.footnote .footnote-text');
      const footnoteRowNodes = [];
      params.api.forEachNode(row => {
        if (row.data.dataType === 'footnote') {  // Test to see if it's a footnote
          footnoteRowNodes.push(row);
        }
      });
    
      if (footnoteCells.length > 0 && footnoteRowNodes.length > 0) {
        footnoteRowNodes.forEach(rowNode => {
          const cellId = 'footnote_' + rowNode.data.id;
          const cell = _.find(footnoteCells, node => node.id === cellId);
          const height = cell.clientHeight;
          rowNode.setRowHeight(height);
        });
        params.api.onRowHeightChanged();
      }
    };
    

    To summarize, the function gets all HTML nodes in the DOM that are footnote text nodes. It then gets all of the table's row nodes that are footnotes. It goes through those row nodes, matching each up with its DOM text. It uses the clientHeight property of the text node and sets the row node height to that value. Finally, it calls the api.onRowHeightChanged() function to let the table know it should reposition and draw the rows.

    Knowing when to calculate the height

    When I set the gridOptions.getRowHeight property to the function above, it didn't work. When the function fires, the footnote rows hadn't yet been rendered, so it was unable to get the clientHeight for the text nodes since they didn't exist.

    Instead, I triggered the function using these event handlers in gridOptions.

    onFirstDataRendered: footnoteRowHeightSetter,
    onBodyScrollEnd: footnoteRowHeightSetter,
    onGridSizeChanged: footnoteRowHeightSetter,
    
    • onFirstDataRendered covers the case where footnotes are on screen when the grid first renders (short table).
    • onBodyScrollEnd covers the case where footnotes aren't on screen at first but the user scrolls to see them.
    • onGridSizeChanged covers the case of grid resizing that alters the wrapping and height of the footnote text.

    This is what worked for me. I like @LennyLip's answer and looking more into it before I select an answer.