Overview
Cell Renderers allow you to customize how cell values are displayed in the grid without entering edit mode. Use cell renderers to:
Format and display complex data structures
Add icons, images, and rich HTML content
Create interactive elements like buttons and links
Display progress bars, charts, and custom visualizations
Implement conditional formatting and styling
Cell renderers are read-only components. For editable cells, use Cell Editors instead.
ICellRendererParams Interface
The grid provides cell renderers with a params object containing all necessary information:
interface ICellRendererParams < TData = any , TValue = any , TContext = any >
extends AgGridCommon < TData , TContext > {
/** Value to be rendered */
value : TValue | null | undefined ;
/** Formatted value (if valueFormatter is defined) */
valueFormatted : string | null | undefined ;
/** True if this is a full width row */
fullWidth ?: boolean ;
/** Pinned state of the cell ('left', 'right', or null) */
pinned ?: 'left' | 'right' | null ;
/** The row's data (can be undefined for row grouping) */
data : TData | undefined ;
/** The row node */
node : IRowNode < TData >;
/** The cell's column definition */
colDef ?: ColDef < TData , TValue >;
/** The cell's column */
column ?: Column < TValue >;
/** The grid's cell DOM element */
eGridCell : HTMLElement ;
/** Parent DOM element for the cell renderer */
eParentOfValue : HTMLElement ;
/** Get the most recent value */
getValue ?: () => TValue | null | undefined ;
/** Set the cell value */
setValue ?: ( value : TValue | null | undefined ) => void ;
/** Format a value using the column's formatter */
formatValue ?: ( value : TValue | null | undefined ) => string ;
/** Refresh the cell */
refreshCell ?: () => void ;
/** Register a row dragger element */
registerRowDragger : (
rowDraggerElement : HTMLElement ,
dragStartPixels ?: number ,
value ?: string ,
suppressVisibilityChange ?: boolean
) => void ;
/** Set a tooltip for this component */
setTooltip : ( value : string , shouldDisplayTooltip ?: () => boolean ) => void ;
}
ICellRenderer Interface
Implement this interface to create a custom cell renderer:
interface ICellRenderer < TData = any > {
/**
* Called when the cell is refreshed.
* Return true if successful, false to destroy and recreate.
*/
refresh ( params : ICellRendererParams < TData >) : boolean ;
}
Complete Component Interface
interface ICellRendererComp < TData = any >
extends IComponent < ICellRendererParams < TData >>,
ICellRenderer < TData > {
/** Initialize the component */
init ( params : ICellRendererParams < TData >) : void ;
/** Return the DOM element */
getGui () : HTMLElement ;
/** Refresh the component */
refresh ( params : ICellRendererParams < TData >) : boolean ;
/** Called after GUI is attached */
afterGuiAttached ? () : void ;
/** Clean up resources */
destroy ? () : void ;
}
Basic Examples
Vanilla JS
React
Angular
Vue
class SimpleCellRenderer {
init ( params ) {
this . eGui = document . createElement ( 'div' );
this . eGui . innerHTML = `
<strong style="color: #04dcfc;">
${ params . value || '' }
</strong>
` ;
}
getGui () {
return this . eGui ;
}
refresh ( params ) {
this . eGui . querySelector ( 'strong' ). textContent = params . value || '' ;
return true ;
}
destroy () {
// Cleanup if needed
}
}
// Column definition
const columnDefs = [
{
field: 'athlete' ,
cellRenderer: SimpleCellRenderer
}
];
import { forwardRef , useImperativeHandle , useState } from 'react' ;
const SimpleCellRenderer = forwardRef (( props , ref ) => {
const [ value , setValue ] = useState ( props . value );
useImperativeHandle ( ref , () => ({
refresh ( params ) {
setValue ( params . value );
return true ;
}
}));
return (
< strong style = { { color: '#04dcfc' } } >
{ value || '' }
</ strong >
);
});
export default SimpleCellRenderer ;
// Column definition
const columnDefs = [
{
field: 'athlete' ,
cellRenderer: SimpleCellRenderer
}
];
import { Component } from '@angular/core' ;
import { ICellRendererAngularComp } from 'ag-grid-angular' ;
import { ICellRendererParams } from 'ag-grid-community' ;
@ Component ({
selector: 'simple-cell-renderer' ,
template: `
<strong style="color: #04dcfc;">
{{ params.value || '' }}
</strong>
`
})
export class SimpleCellRenderer implements ICellRendererAngularComp {
public params : ICellRendererParams ;
agInit ( params : ICellRendererParams ) : void {
this . params = params ;
}
refresh ( params : ICellRendererParams ) : boolean {
this . params = params ;
return true ;
}
}
// Column definition
columnDefs = [
{
field: 'athlete' ,
cellRenderer: SimpleCellRenderer
}
];
< template >
< strong style = " color : #04dcfc ; " >
{{ params . value || '' }}
</ strong >
</ template >
< script >
export default {
data () {
return {
params: null
};
} ,
methods: {
refresh ( params ) {
this . params = params ;
return true ;
}
}
} ;
</ script >
// Column definition
const columnDefs = [
{
field: 'athlete',
cellRenderer: SimpleCellRenderer
}
];
Advanced Examples
Vanilla JS
React
Angular
Vue
class ButtonCellRenderer {
init ( params ) {
this . params = params ;
this . eGui = document . createElement ( 'div' );
this . eButton = document . createElement ( 'button' );
this . eButton . className = 'btn-simple' ;
this . eButton . textContent = 'Click Me' ;
this . eventListener = () => {
alert ( `Clicked: ${ params . data . athlete } ` );
};
this . eButton . addEventListener ( 'click' , this . eventListener );
this . eGui . appendChild ( this . eButton );
}
getGui () {
return this . eGui ;
}
refresh () {
return false ; // Don't refresh, recreate instead
}
destroy () {
if ( this . eventListener ) {
this . eButton . removeEventListener ( 'click' , this . eventListener );
}
}
}
Image Renderer with Fallback
class ImageCellRenderer {
init ( params ) {
this . eGui = document . createElement ( 'div' );
this . eGui . className = 'image-cell' ;
const img = document . createElement ( 'img' );
img . src = params . value || 'default-avatar.png' ;
img . alt = params . data . name ;
img . style . width = '32px' ;
img . style . height = '32px' ;
img . style . borderRadius = '50%' ;
img . onerror = () => {
img . src = 'default-avatar.png' ;
};
this . eGui . appendChild ( img );
}
getGui () {
return this . eGui ;
}
refresh ( params ) {
const img = this . eGui . querySelector ( 'img' );
img . src = params . value || 'default-avatar.png' ;
img . alt = params . data . name ;
return true ;
}
}
Status Badge Renderer
class StatusCellRenderer {
init ( params ) {
this . eGui = document . createElement ( 'span' );
this . refresh ( params );
}
getGui () {
return this . eGui ;
}
refresh ( params ) {
const status = params . value ?. toLowerCase ();
const statusConfig = {
active: { color: '#10b981' , label: 'Active' },
pending: { color: '#f59e0b' , label: 'Pending' },
inactive: { color: '#ef4444' , label: 'Inactive' }
};
const config = statusConfig [ status ] || statusConfig . inactive ;
this . eGui . innerHTML = `
<span style="
background-color: ${ config . color } 20;
color: ${ config . color } ;
padding: 4px 12px;
border-radius: 12px;
font-size: 12px;
font-weight: 600;
">
${ config . label }
</span>
` ;
return true ;
}
}
Cell Renderer Functions
For simple cases, you can use a function instead of a class:
const columnDefs = [
{
field: 'price' ,
cellRenderer : ( params ) => {
if ( params . value == null ) return '' ;
return `$ ${ params . value . toFixed ( 2 ) } ` ;
}
},
{
field: 'status' ,
cellRenderer : ( params ) => {
const icon = params . value === 'active' ? '✓' : '✗' ;
return `<span> ${ icon } ${ params . value } </span>` ;
}
}
];
Cell renderer functions cannot implement the refresh() method. The cell will be recreated on every data change, which may impact performance.
Built-in Cell Renderers
AG Grid provides several built-in cell renderers:
Checkbox Cell Renderer
const columnDefs = [
{
field: 'selected' ,
cellRenderer: 'agCheckboxCellRenderer' ,
cellRendererParams: {
disabled: false
}
}
];
Group Cell Renderer
const columnDefs = [
{
field: 'country' ,
cellRenderer: 'agGroupCellRenderer' ,
cellRendererParams: {
innerRenderer : ( params ) => params . value ,
suppressCount: false
}
}
];
Suppressing Mouse Event Handling
Prevent the grid from handling mouse events in your cell renderer:
interface EventCellRendererParams < TData = any , TValue = any , TContext = any > {
suppressMouseEventHandling ?: (
params : SuppressMouseEventHandlingParams < TData , TValue , TContext >
) => boolean ;
}
interface SuppressMouseEventHandlingParams < TData = any , TValue = any , TContext = any > {
node : IRowNode < TData >;
column ?: Column < TValue >;
event : MouseEvent ;
}
Example usage:
const columnDefs = [
{
field: 'action' ,
cellRenderer: ButtonCellRenderer ,
suppressMouseEventHandling : ( params ) => {
// Prevent grid from handling clicks on buttons
return params . event . target . tagName === 'BUTTON' ;
}
}
];
Row Dragging
Register elements as row drag handles:
class DragHandleCellRenderer {
init ( params ) {
this . eGui = document . createElement ( 'div' );
this . eGui . innerHTML = `
<div class="drag-handle">⋮⋮</div>
<span> ${ params . value } </span>
` ;
const dragHandle = this . eGui . querySelector ( '.drag-handle' );
params . registerRowDragger ( dragHandle );
}
getGui () {
return this . eGui ;
}
refresh () {
return false ;
}
}
Set custom tooltips from your cell renderer:
class TooltipCellRenderer {
init ( params ) {
this . eGui = document . createElement ( 'div' );
this . eGui . textContent = params . value ;
// Set tooltip
params . setTooltip (
`Full value: ${ params . value } ` ,
() => params . value ?. length > 20 // Only show if value is long
);
}
getGui () {
return this . eGui ;
}
refresh () {
return true ;
}
}
Best Practices
Implement refresh() for Performance
Always remove event listeners in the destroy() method: destroy () {
if ( this . clickListener ) {
this . eButton . removeEventListener ( 'click' , this . clickListener );
}
}
Use valueFormatted When Available
Handle Null and Undefined Values
Always check for null/undefined values: init ( params ) {
const value = params . value ?? 'N/A' ;
this . eGui . textContent = value ;
}
TypeScript Support
Use generics for type-safe cell renderers:
interface Athlete {
name : string ;
country : string ;
sport : string ;
}
class TypedCellRenderer implements ICellRendererComp < Athlete > {
private eGui : HTMLElement ;
private params : ICellRendererParams < Athlete >;
init ( params : ICellRendererParams < Athlete >) : void {
this . params = params ;
this . eGui = document . createElement ( 'div' );
// TypeScript knows params.data is Athlete
this . eGui . textContent = ` ${ params . data . name } - ${ params . data . country } ` ;
}
getGui () : HTMLElement {
return this . eGui ;
}
refresh ( params : ICellRendererParams < Athlete >) : boolean {
this . params = params ;
this . eGui . textContent = ` ${ params . data . name } - ${ params . data . country } ` ;
return true ;
}
}
Next Steps
Cell Editors Learn about custom cell editors for data input
Filters Create custom filter components