Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/ag-grid/ag-grid/llms.txt

Use this file to discover all available pages before exploring further.

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

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
  }
];

Advanced Examples

Button Renderer with Event Handling

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;
  }
}

Tooltips

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

Always try to implement refresh() to update your component instead of recreating it. Return true if successful, false to recreate:
refresh(params) {
  // Update existing DOM instead of recreating
  this.eGui.querySelector('.value').textContent = params.value;
  return true; // Successfully refreshed
}
Always remove event listeners in the destroy() method:
destroy() {
  if (this.clickListener) {
    this.eButton.removeEventListener('click', this.clickListener);
  }
}
The valueFormatted parameter contains the formatted value if a valueFormatter is defined:
init(params) {
  const displayValue = params.valueFormatted ?? params.value;
  this.eGui.textContent = displayValue;
}
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