Cell Rendering

Cell Rendering - this is a very powerful feature in ag-Grid. With this, you can put whatever you want in the grid. The job of the grid is to lay out the cells. What goes into the cells, that's where you come in! You customise the rendering inside the cells by providing 'cellRenderers'.

You configure cellRenderers as part of the column definition and can be one of the following:

  • function: The cellRenderer is a function that gets called once for each cell. The function should return a string (which will be treated as html) or a DOM object. Use this if you have no cleanup or refresh requirements of the cell - it's a 'fire and forget' approach to the cell rendering.
  • component: The grid will call 'new' on the provided class and treat the object as a component, using lifecycle methods. Use this if you need to do cleanup when the cell is removed or have refresh requirements.
  • string: The cellRenderer is looked up from the provided cellRenderers. Use this if you want to use a built in renderer (eg 'group') or you want to register your own cellRenderers for reuse.

cellRenderer Function

The easiest (but not as flexible) way to provide your own cellRenderer is to provide a function. The function takes a set of parameters (with information on what to render) and you return back either a) a string of HTML or b) a DOM object.

Below are some simple examples of cellRenderer function:

// put the value in bold
colDef.cellRenderer = function(params) {
    return '<b>' + params.value.toUpperCase() + '</b>';

// put a tooltip on the value
colDef.cellRenderer = function(params) {
    return '<span title="the tooltip">'+params.value+'</span>';

// create a DOM object 
colDef.cellRenderer = function(params) {
    var eDiv = document.createElement('div');
    eDiv.innerHTML = '<span class="my-css-class"><button class="btn-simple">Push Me</button></span>';
    var eButton = eDiv.querySelectorAll('.btn-simple')[0];

    var eButton.addEventListener('click', function() {
        console.log('button was clicked!!');

    return eDiv;

See further below for the set of parameters passed to the rendering function.

cellRenderer Component

The most flexible (but a little more tricky) way to provide a cellRenderer is to provide a component class. The component class that you provide can have callback methods on it for refresh and destroy.

A cellRenderer Component is an ag-Grid concept that is similar in how 'components' work in other frameworks. Other than sharing the same concept and name, ag-Grid Components have nothing to do with Angular components, React components, or any other components.

An ag-Grid cellRenderer Component does not need to extend any class or do anything except implement the methods shown in the interface.

The interface for the cellRenderer component is as follows:

interface ICellRendererComp {
    // Optional - Params for rendering. The same params that are passed to the cellRenderer function.
    init?(params: any): void;

    // Mandatory - Return the DOM element of your editor, this is what the grid puts into the DOM
    getGui(): HTMLElement;

    // Optional - Gets called once by grid after editing is finished - if your editor needs to do any cleanup,
    // do it here
    destroy?(): void;

    // Optional - Get the cell to refresh. If this method is not provided, then when refresh is needed, the grid
    // will remove the component from the DOM and create a new component in it's place with the new values.
    refresh?(params: any): void;

Below is a simple example of cellRenderer class:

// function to act as a class
function MyCellRenderer () {}

// gets called once before the renderer is used
MyCellRenderer.prototype.init = function(params) {
    // create the cell
    this.eGui = document.createElement('div');
    this.eGui.innerHTML = '<span class="my-css-class"><button class="btn-simple">Push Me</button><span class="my-value"></span></span>';

    // get references to the elements we want
    this.eButton = this.eGui.querySelectorAll('.btn-simple')[0];
    this.eValue = this.eGui.querySelectorAll('.my-value')[0];

    // set value into cell
    this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;

    // add event listener to button
    this.eventListener = function() {
        console.log('button was clicked!!');
    this.eButton.addEventListener('click', this.eventListener);

// gets called once when grid ready to insert the element
MyCellRenderer.prototype.getGui = function() {
    return this.eGui;

// gets called whenever the user gets the cell to refresh
MyCellRenderer.prototype.refresh = function(params) {
    // set value into cell again
    this.eValue.innerHTML = params.valueFormatted ? params.valueFormatted : params.value;

// gets called when the cell is removed from the grid
MyCellRenderer.prototype.destroy = function() {
    // do cleanup, remove event listener from button
    this.eButton.removeEventListener('click', this.eventListener);

cellRenderer Component Refresh

The grid is constantly refreshing rows and cells into the browser, but not every refresh of the grid results in the refresh method of your cellRenderer getting called. The following details when your cellRenderer refresh method gets called and when not.

The following will result in cellRenderer refresh method getting called:

  • Calling rowNode.setDataValue(colKey, value) to set a value directly onto the rowNode
  • When editing a cell and editing is stopped, so that cell displays new value after editing.
  • Calling api.refreshCells(rowNodes, colIds) to inform grid data has changed (see Refresh).
  • Calling api.softRefreshView() to inform grid data has changed (see Refresh).
If any of the above occur, the refresh() method will be called if it is provided. If not, the component will be destroyed and replaced.

The following will not result in cellRenderer refresh method getting called:

  • Calling rowNode.setData(data) to set new data into a rowNode.
  • Scrolling the grid vertically (results in rows getting ripped in / out of the dom).
  • All other api refresh methods (refreshRows, refreshView etc).
All of the above will result in the component getting destrotyed and recreated.

cellRenderer Component Lifecycle

The lifecycle of the cellRenderer is as follows:

  • new is called on the class.
  • init() is called once.
  • getGui() is called once.
  • refresh() is called 0..n times (ie it may never be called, or called multiple times)
  • destroy() is called once.
In other words, new(), init(), getGui() and destroy() are always called exactly once. refresh() is optionally called multiple times.

If you are implementing refresh(), remember that getGui() is only called once, so be sure to update the existing GUI in your refresh, do not think that the grid is going to call getGui() again to get a new version of the GUI.

cellRenderer Params

The cellRenderer function and cellRenderer component take parameters as follows:

  • cellRenderer function: Passed to function.
  • cellRenderer component: Passed to init method.
The parameters are identical regardless of which cellRenderer type you use and contain the following:

Value Description
value The value to be rendered.
valueFormatted If a valueFormatter was provided, is the result of calling the formatter.
valueGetter A function, that when called, gives you the value, calling the relevant valueGetter / expression if necessary. This can be called at any time after rendering should the value change and you find the refresh functionality provided by the grid is not enough.
formatValue A function, that when called, formats the value. The valueFormatted attribute already gives you the formatted value, however you can call this if you need to format another value, maybe you need to format a different value (this is used by the provided 'animation' cellRenderers where they need to format the delta difference).
node The RowNode of the row being rendered.
data The row (from the rowData array, where value was taken) been rendered.
column The column been rendered (in ag-Grid, each colDef is wrapped by a Column).
colDef The colDef been rendered.
$scope If compiling to Angular, is the row's child scope, otherwise null.
rowIndex The index of the row, after sorting and filtering.
api A reference to the grid api.
columnApi A reference to the column api.
context The context as set on the gridOptions.
refreshCell A callback function, to tell the grid to refresh this cell and reapply all css styles and classes. Useful if you update the data for the cell and want to just render again from scratch.
eGridCell A reference to the DOM element representing the grid cell that your component will live inside. Useful if you want to add event listeners or classes at this level. This is the DOM element that gets browser focus when selecting cells.
eParentOfValue If using checkbox selection, your component will live inside eParentOfValue which sits beside a checkbox and both live inside eGridCell.

Complementing cellRenderer Params

On top of the parameters provided by the grid, you can also provide your own parameters. This is useful if you want to 'configure' your cellRenderer. For example, you might have a cellRenderer for formatting currency but you need to provide what currency for your cellRenderer to use.

Provide params to a cellRenderer using the colDef option cellRendererParams.

// define cellRenderer to be reused
var myCellRenderer = function(params) {
    return '<span style="color: '+params.color+'">' + params.value + '</span>';

// use with a color
colDef.cellRenderer = myCellRenderer;
colDef.cellRendererParams = {
    color: 'guinnessBlack'

// use with another color
colDef.cellRenderer = myCellRenderer;
colDef.cellRendererParams = {
    color: 'irishGreen'

Provided cellRenderers

Instead of providing a cellRenderer function or component, you can select from ones that come with the grid or install your own into the grid.

The cellRenderers provided by the grid are as follows:

  • group: For group rendering.
  • animateShowChange: Cell renderer that when data changes, it animates showing the difference by showing the delta for a period of time.
  • animateSlide: Cell renderer that when data changes, it animates showing the old value fading away to the left.

From the provided cellRenderers, it is intended the you use 'group' as is, however 'animateShowChange' and 'animateSlide' are given as examples on what is possible. How you show changes or otherwise want to refresh is going to be different for everyone. So take influence from what you see, but consider creating your own.

Usage of group cellRenderer is detailed in the section Grouping Rows and Aggregation.

Usage of animateShowChange and animateSlide is demonstrated in the section Viewport.

Example: Using cellRenderers

The example below shows five columns formatted, demonstrating each of the methods above.

  • 'Month' column uses cellStyle to format each cell in the column with the same style.
  • 'Max Temp' and 'Min Temp' columns uses the Function method to format each cell in the column with the same style.
  • 'Days of Air Frost' column uses the Component method to format each cell in the column with the same style
  • 'Days Sunshine' and 'Rainfall (10mm)' use simple functions to display icons.

Cell Renderers and Row Groups

If you are mixing cellRenderers and row grouping, then you need to understand that the value and / or data may be missing in the group row. The data and value will be missing if you are not doing any aggregations (hence no data at the group level) and the value will be missing if you are doing aggregations but not on the column the cellRenderer is on.

This is simply fixed by checking for the existence of the data before you use it like the following:

colDef.cellRenderer = function(params) {

    // check the data exists, to avoid error when grouping but not aggregating
    if (params.data) {
        // data exists, so we can access it
        return '<b>'+params.data.theBoldValue+'</b>';
    } else {
        // when we return null, the grid will display a blank cell
        return null;