Skip to main content
The IHeaderComp interface allows you to create custom components for column headers in AG Grid. Header components control how column headers are displayed and can add custom functionality like sorting, filtering, or custom interactions.

Overview

Create custom header components to add specialized header displays, custom sorting controls, or additional header functionality.
const gridOptions = {
  columnDefs: [
    {
      field: 'name',
      headerComponent: CustomHeaderComponent
    }
  ]
};

Interface Definition

interface IHeaderComp extends IHeader, IComponent<IHeaderParams> {
  /** Get the header to refresh */
  refresh(params: IHeaderParams): boolean;
}

interface IHeader {
  /** Get the header to refresh. Gets called whenever Column Defs are updated. */
  refresh(params: IHeaderParams): boolean;
}

IHeaderParams

column
Column
The column the header is for.
init(params) {
  this.column = params.column;
  console.log('Header for:', params.column.getId());
}
displayName
string
The name to display for the column. If the column is using a headerValueGetter, the displayName will take this into account.
init(params) {
  this.eText.textContent = params.displayName;
}
enableSorting
boolean | undefined
Whether sorting is enabled for the column. Only put sort logic into your header if this is true.
init(params) {
  if (params.enableSorting) {
    this.setupSorting();
  }
}
enableMenu
boolean
Whether menu is enabled for the column. Only display a menu button in your header if this is true.
init(params) {
  if (params.enableMenu) {
    this.eMenu.style.display = 'block';
  }
}
enableFilterButton
boolean
Whether filter button should be displayed in the header (for new column menu).
init(params) {
  if (params.enableFilterButton) {
    this.eFilterButton.style.display = 'block';
  }
}
enableFilterIcon
boolean
Whether filter icon should be displayed in the header (for legacy tabbed column menu).
init(params) {
  if (params.enableFilterIcon) {
    this.eFilterIcon.style.display = 'block';
  }
}
eGridHeader
HTMLElement
The header the grid provides. The custom header component is a child of the grid provided header. This is provided should you want to make changes to this cell, eg add ARIA tags, or add keyboard event listener.
init(params) {
  params.eGridHeader.setAttribute('aria-label', 'Custom header');
}

Callback Methods

showColumnMenu
(source: HTMLElement, onClosedCallback?: () => void) => void
Callback to request the grid to show the column menu. Pass in the html element of the column menu button to have the grid position the menu over the button.
onMenuClick(event) {
  this.params.showColumnMenu(this.eMenuButton);
}
showColumnMenuAfterMouseClick
(mouseEvent: MouseEvent | Touch, onClosedCallback?: () => void) => void
Callback to request the grid to show the column menu. Similar to showColumnMenu, but will position the menu next to the provided mouseEvent.
onContextMenu(event) {
  event.preventDefault();
  this.params.showColumnMenuAfterMouseClick(event);
}
showFilter
(source: HTMLElement) => void
Callback to request the grid to show the filter. Pass in the html element of the filter button to have the grid position the menu over the button.
onFilterClick() {
  this.params.showFilter(this.eFilterButton);
}
progressSort
(multiSort?: boolean) => void
Callback to progress the sort for this column. The grid will decide the next sort direction eg ascending, descending or ‘no sort’. Pass multiSort=true if you want to do a multi sort (eg user has Shift held down when they click).
onSortClick(event) {
  this.params.progressSort(event.shiftKey);
}
setSort
(sort: SortDirection | SortDef, multiSort?: boolean) => void
Callback to set the sort for this column. Pass the sort direction to use ignoring the current sort. Pass multiSort=true if you want to do a multi sort.
onAscClick() {
  this.params.setSort('asc');
}
setTooltip
(value: string, shouldDisplayTooltip?: () => boolean) => void
Sets a tooltip to the main element of this component.Module: TooltipModule
init(params) {
  params.setTooltip('Click to sort');
}

Template Properties

template
string
Custom header template if provided to headerComponentParams, otherwise will be undefined.
init(params) {
  if (params.template) {
    this.eGui.innerHTML = params.template;
  }
}
innerHeaderComponent
any
The component to use for inside the header (replaces the text value and leaves the remainder of the Grid’s original component).
// In column definition
{
  field: 'name',
  headerComponentParams: {
    innerHeaderComponent: CustomInnerHeader
  }
}

Required Methods

refresh
(params: IHeaderParams) => boolean
Get the header to refresh. Gets called whenever Column Defs are updated. Return true if the refresh was successful, false if not (then grid will destroy and recreate the component).
refresh(params) {
  this.params = params;
  this.eText.textContent = params.displayName;
  this.updateSortIndicator();
  return true;
}

Complete Example

class CustomHeaderComponent {
  init(params) {
    this.params = params;
    
    // Create GUI
    this.eGui = document.createElement('div');
    this.eGui.className = 'custom-header';
    this.eGui.innerHTML = `
      <div class="custom-header-label">
        <span class="header-text"></span>
        <span class="sort-indicator"></span>
      </div>
      <button class="header-menu-button">☰</button>
    `;
    
    // References to elements
    this.eText = this.eGui.querySelector('.header-text');
    this.eSortIndicator = this.eGui.querySelector('.sort-indicator');
    this.eMenuButton = this.eGui.querySelector('.header-menu-button');
    
    // Set text
    this.eText.textContent = params.displayName;
    
    // Setup sorting
    if (params.enableSorting) {
      this.onSortRequested = this.onSortRequested.bind(this);
      this.eText.addEventListener('click', this.onSortRequested);
      this.eText.style.cursor = 'pointer';
    }
    
    // Setup menu
    if (params.enableMenu) {
      this.onMenuClick = this.onMenuClick.bind(this);
      this.eMenuButton.addEventListener('click', this.onMenuClick);
    } else {
      this.eMenuButton.style.display = 'none';
    }
    
    // Update sort indicator
    this.updateSortIndicator();
  }
  
  onSortRequested(event) {
    this.params.progressSort(event.shiftKey);
  }
  
  onMenuClick() {
    this.params.showColumnMenu(this.eMenuButton);
  }
  
  updateSortIndicator() {
    const sort = this.params.column.getSort();
    if (sort === 'asc') {
      this.eSortIndicator.textContent = '↑';
    } else if (sort === 'desc') {
      this.eSortIndicator.textContent = '↓';
    } else {
      this.eSortIndicator.textContent = '';
    }
  }
  
  getGui() {
    return this.eGui;
  }
  
  refresh(params) {
    this.params = params;
    this.eText.textContent = params.displayName;
    this.updateSortIndicator();
    return true;
  }
  
  destroy() {
    if (this.params.enableSorting) {
      this.eText.removeEventListener('click', this.onSortRequested);
    }
    if (this.params.enableMenu) {
      this.eMenuButton.removeEventListener('click', this.onMenuClick);
    }
  }
}

// Usage
const gridOptions = {
  columnDefs: [
    {
      field: 'name',
      headerComponent: CustomHeaderComponent,
      sortable: true,
      menuTabs: ['filterMenuTab', 'generalMenuTab']
    }
  ]
};

Header Templates

You can also provide a simple HTML template for the header:
const gridOptions = {
  columnDefs: [
    {
      field: 'name',
      headerComponentParams: {
        template:
          '<div>' +
          '  <span class="custom-icon">🔍</span>' +
          '  <span class="ag-header-cell-text" ref="eText"></span>' +
          '</div>'
      }
    }
  ]
};

Column Definitions

Configure header components in columns

Column Events

Header interaction events

GridApi

Programmatic column control