Framework:Javascript Data GridAngular Data GridReact Data GridVue Data Grid

React Data Grid: Custom Detail

When a Master Row is expanded, the grid uses the default Detail Cell Renderer to create and display the Detail Grid inside one row of the Master Grid. You can provide a customer Detail Cell Renderer to display something else if the default Detail Cell Renderer doesn't do what you want.

Configure the grid to use a customer Detail Cell Renderer using the grid property detailCellRenderer.

// normally left blank, the grid will use the default Detail Cell Renderer
const detailCellRenderer = 'myCellRendererComp';

// params sent to the Detail Cell Renderer, in this case your MyCellRendererComp
const detailCellRendererParams = {};

<AgGridReact detailCellRenderer={detailCellRenderer} detailCellRendererParams={detailCellRendererParams}></AgGridReact>

The Detail Cell Renderer should be a Cell Renderer component. See Cell Renderer on how to build and register a Cell Renderer with the grid.

The following examples demonstrate minimalist custom Detail Cell Renderer. Note that where a Detail Grid would normally appear, only the message "My Customer Detail" is shown.

Custom Detail With Form

It is not mandatory to display a grid inside the detail section. As you are providing a custom component, there are no restrictions as to what can appear inside the custom component.

This example shows a custom Detail Cell Renderer that uses a form rather than a grid.

Custom Detail With Grid

It is possible to provide a Customer Detail Grid that does a similar job to the default Detail Cell Renderer. This example demonstrates displaying a custom grid as the detail.

Register Detail Grid

In order for the Detail Grid's API to be available via the Master Grid as explained in Accessing Detail Grids, a Grid Info object needs to be registered with the Master Grid.

Register a detail grid with the master grid when it is created.
addDetailGridInfo = (
    id: string,
    gridInfo: DetailGridInfo
) => void;

interface DetailGridInfo {
  // Id of the detail grid, the format is `detail_<ROW_ID>`,
  // where ROW_ID is the `id` of the parent row. 
  id: string;
  // Grid api of the detail grid. 
  api?: GridApi;
  // Column api of the detail grid. 
  columnApi?: ColumnApi;
Unregister a detail grid from the master grid when it is destroyed.
removeDetailGridInfo = (id: string) => void;

When the Detail Grid is created, register it via masterGridApi.addDetailGridInfo(id, info) and when the Detail Grid is destroyed, unregister it via masterGridApi.removeDetailGridInfo(id). A Detail ID is required when calling these methods. Any unique ID can be used, however for consistency with how the default Detail Cell Renderer works it's recommended to use the ID of the detail Row Node.

// Register with Master Grid
const detailId =;

// Create Grid Info object
const detailGridInfo = {
    id: detailId,
    api: params.api,
    columnApi: params.columnApi

this.masterGridApi.addDetailGridInfo(detailId, detailGridInfo);

// Unregister with Master Grid


When data is updated in the grid using Transaction Updates, the grid will call refresh on all Detail Cell Renderer's.

It is up to the Detail Cell Renderer whether it wants to act on the refresh or not. If the refresh() method returns true, the grid will assume the Detail Cell Renderer has refreshed successfully and nothing more will happen. However if false is returned, the grid will destroy the Detail Cell Renderer and re-create it again.

This pattern is similar to how refresh works for normal grid Cell Renderer's.

The example below shows how components can optionally refresh on updates. The example refreshes the first row every one second. The refresh() method gets called on all Detail Cell Renderers after the transaction is applied. Only the first Detail Cell Renderer returns false so it is the only one that updates.

The creation time is printed to each Detail Cell Renderer so it can be noted when it was last created.

In this simple example, it would be possible for the components to just update themselves and not rely on the grid destroying and re-creating the components. However the example is contrived to demonstrate returning true vs false from the refresh method.