Tooltips can be set for cells and column headers.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
{
headerName: "Athlete",
field: "athlete",
// here the Athlete column will tooltip the Country value
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
headerName: "Hover For Tooltip",
headerTooltip: "Column Groups can have Tooltips also",
children: [
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
],
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; The following Column Definition properties configure tooltips:
Tooltip for the cell. true shows the displayed cell value (valueFormatted when present, otherwise value). false disables tooltip content configured on the Column Definition. |
Use tooltip: true for the common case where the tooltip should match the displayed cell value. This uses valueFormatted when present, otherwise value, regardless of whether the value came from field or valueGetter.
const [columnDefs, setColumnDefs] = useState([
{ field: 'price', valueFormatter: priceFormatter, tooltip: true },
{ field: 'status', tooltip: 'Current status' },
{ field: 'athlete', tooltip: (params) => `Country: ${params.data?.country}` },
{ field: 'internalId', tooltip: false },
]);
<AgGridReact columnDefs={columnDefs} />tooltip: false disables cell tooltip content supplied by tooltip, tooltipField, or tooltipValueGetter. Tooltips supplied at runtime by a Cell Renderer using setTooltip, and grid-owned validation or formula error tooltips, remain available. These independent tooltip sources continue to use the column's tooltipComponent and tooltipComponentParams when configured.
The same value forms are accepted by headerTooltip. With headerTooltip: true, the displayed header name is used. Setting headerTooltip: false does not disable a tooltip supplied at runtime by a custom Header Component using setTooltip.
Tooltip Callback Copy Link
Cell and header tooltip callbacks receive the same parameters. value is the underlying cell value or displayed header name, and valueFormatted contains the formatted value when available.
Properties available on the TooltipCallbackParams<TData = any, TValue = any, TContext = any> interface.
What part of the application is showing the tooltip, e.g. 'cell', 'header', or 'menu'. |
The source value. For cell tooltips, this is the cell value before tooltip content is resolved. |
The formatted source value, when available. |
Column / ColumnGroup definition. |
Column / ColumnGroup |
The index of the row containing the cell rendering the tooltip. |
The row node. |
Data for the row node in question. |
The grid api. |
Application context as set on gridOptions.context. |
Tooltips for Truncated Text Copy Link
It's possible to configure tooltips to show only when the items hovered are truncated by setting tooltipShowMode = 'whenTruncated'.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
field: "athlete",
tooltip: true,
width: 130,
},
{
field: "country",
tooltip: true,
headerName: "Country of Athlete",
headerTooltip: "Country of Athlete",
width: 100,
},
{
field: "sport",
tooltip: true,
},
]);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
tooltipShowDelay={500}
tooltipShowMode={"whenTruncated"}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; tooltipShowMode = 'whenTruncated' has no effect when using Browser Tooltips, as Browser Tooltips are controlled by the browser and not the grid.
Show and Hide Delay Copy Link
By default, tooltips show after 2 seconds and hide after 10 seconds. These delays can be configured in milliseconds:
The delay in milliseconds that it takes for tooltips to show up once an element is hovered over.
Note: This property does not work if enableBrowserTooltips is true. |
The delay in milliseconds before a tooltip is shown when moving the pointer from one tooltip-enabled element to
another while the previous tooltip is still visible or pending hide.
Note: This property does not work if enableBrowserTooltips is true. |
The delay in milliseconds that it takes for tooltips to hide once they have been displayed.
Note: This property does not work if enableBrowserTooltips is true and tooltipHideTriggers includes timeout. |
const tooltipShowDelay = 0;
const tooltipSwitchShowDelay = 1000;
const tooltipHideDelay = 2000;
<AgGridReact
tooltipShowDelay={tooltipShowDelay}
tooltipSwitchShowDelay={tooltipSwitchShowDelay}
tooltipHideDelay={tooltipHideDelay}
/>"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "Athlete",
field: "athlete",
tooltipComponentParams: { color: "#55AA77" },
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={0}
tooltipSwitchShowDelay={1000}
tooltipHideDelay={2000}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Setting delays will have no effect if using Browser Tooltips as Browser Tooltips are controlled by the browser and not the grid.
Blank Values Copy Link
Tooltips are not shown for the missing values undefined, null and "" (empty string). To display a tooltip for a missing value, use a callback that returns non-empty content.
In the example below:
- The data has missing values
undefined,nulland''(empty String) as the first three rows. - Column A uses
tooltip: true, so no tooltip is shown for a missing displayed value. - Column B uses a
tooltipcallback to return fallback content, so a tooltip is shown.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
GridReadyEvent,
ModuleRegistry,
TooltipCallbackParams,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const getTooltip = (params: TooltipCallbackParams) =>
params.value == null || params.value === "" ? "- Missing -" : params.value;
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<any[]>();
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "A - Missing Value, NO Tooltip",
field: "athlete",
tooltip: true,
},
{
headerName: "B - Missing Value, WITH Tooltip",
field: "athlete",
tooltip: getTooltip,
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const onGridReady = useCallback((params: GridReadyEvent) => {
fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
.then((resp) => resp.json())
.then((data: any[]) => {
// set some blank values to test tooltip against
data[0].athlete = undefined;
data[1].athlete = null;
data[2].athlete = "";
setRowData(data);
});
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact
rowData={rowData}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
onGridReady={onGridReady}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
Row Groups Copy Link
When a column is grouped, the generated group column inherits tooltip, tooltipComponent, and tooltipComponentParams from the underlying column's Column Definition. This is consistent with how valueFormatter is inherited. With groupDisplayType: 'multipleColumns', the group column header also inherits headerTooltip.
Cell tooltip properties set on autoGroupColumnDef (tooltip and tooltipComponent) apply to leaf rows only. headerTooltip still applies to the group column header.
In the example below:
- The Country and Year columns each define a
tooltipcallback. Hover a group key to see the tooltip inherited from the underlying column. autoGroupColumnDefdefines atooltipcallback. Hover a leaf row in the group column to see it.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
AutoGroupColumnDef,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import {
ColumnMenuModule,
ColumnsToolPanelModule,
ContextMenuModule,
RowGroupingModule,
SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [
TooltipModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
ColumnMenuModule,
ContextMenuModule,
RowGroupingModule,
SetFilterModule,
];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
field: "country",
width: 120,
rowGroup: true,
hide: true,
// inherited by group rows in the group column
tooltip: (params) => `Country: ${params.value}`,
},
{
field: "year",
width: 90,
rowGroup: true,
hide: true,
// inherited by group rows in the group column
tooltip: (params) => `Year: ${params.value}`,
},
{ field: "athlete", width: 200 },
{ field: "age", width: 90 },
{ field: "sport", width: 110 },
]);
const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
return {
headerTooltip: "Group",
minWidth: 190,
// applies to leaf rows only; group rows inherit from their colDef
tooltip: (params) => `Athlete: ${params.value}`,
};
}, []);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
autoGroupColumnDef={autoGroupColumnDef}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; autoGroupColumnDef cell tooltip properties apply to leaf rows only. Group rows inherit their cell tooltips from the underlying column colDef.
Grouped Column Headers Copy Link
With groupDisplayType: 'multipleColumns', each generated group column header inherits the headerTooltip from its underlying column colDef. Hover a group column header in the example below to see the inherited tooltip.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
RowGroupingDisplayType,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule, RowGroupingModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
field: "country",
rowGroup: true,
hide: true,
// inherited by the generated group column header
headerTooltip: "Group by Country",
},
{
field: "year",
rowGroup: true,
hide: true,
// inherited by the generated group column header
headerTooltip: "Group by Year",
},
{ field: "athlete" },
{ field: "sport" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
groupDisplayType={"multipleColumns"}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Full Width Group Rows Copy Link
With groupDisplayType: 'groupRows', full-width group rows inherit their tooltips from the underlying column colDef. Hover a group row in the example below to see the tooltip defined on the grouped column.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
RowGroupingDisplayType,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { RowGroupingModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule, RowGroupingModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
field: "country",
rowGroup: true,
hide: true,
// shown on the full-width group row inherited from this colDef
tooltip: (params) => `Country: ${params.value}`,
},
{
field: "year",
rowGroup: true,
hide: true,
// shown on the full-width group row inherited from this colDef
tooltip: (params) => `Year: ${params.value}`,
},
{ field: "athlete" },
{ field: "sport" },
{ field: "total" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
groupDisplayType={"groupRows"}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Aggregated Cells Copy Link
When a group row displays an aggregated value in a data column, hovering that cell shows a tooltip for the aggregated value, not the underlying row data.
Touch Devices Copy Link
On iOS and Android, press and hold a tooltip-enabled grid element to show its rich HTML tooltip. The tooltip opens as soon as the long press is recognised, without applying tooltipShowDelay a second time. Moving the touch before the long press completes cancels the gesture. Tap elsewhere to dismiss the tooltip. Grid gestures that already use the long press, such as the context menu and column menu, take precedence over the tooltip. Setting suppressTouch=true disables this gesture. Browser Tooltips remain controlled by the browser.
Mouse Tracking Copy Link
The example below enables mouse tracking to demonstrate a scenario where tooltips need to follow the cursor. To enable this feature, set the tooltipMouseTrack to true in the gridOptions.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "Athlete",
field: "athlete",
tooltipComponentParams: { color: "#55AA77" },
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
tooltipMouseTrack={true}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Browser Tooltip Copy Link
Set the grid property enableBrowserTooltips=true to stop using rich HTML Components and use the browsers native tooltip.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "Athlete",
field: "athlete",
tooltipComponentParams: { color: "#55AA77" },
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
enableBrowserTooltips={true}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Interactive Tooltips Copy Link
By default, tooltips cannot be interacted with and hovering them has no effect. If tooltipInteraction=true is set in the grid options, tooltips remain visible while being hovered and their content can be selected or activated.
const tooltipInteraction = true;
<AgGridReact tooltipInteraction={tooltipInteraction} />The example below enables Tooltip Interaction to demonstrate a scenario where tooltips will not disappear while hovered. Note following:
- Tooltips will not disappear while being hovered.
- Tooltips content can be selected and copied.
Tabmoves focus into focusable tooltip content andEscapecloses the tooltip.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "Athlete",
field: "athlete",
tooltipComponentParams: { color: "#55AA77" },
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={500}
tooltipInteraction={true}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; The example below shows Tooltip Interaction with Custom Tooltips. Note the following:
- Tooltip is enabled for the Athlete and Age columns.
- Tooltips will not disappear while being hovered.
- The custom tooltip displays a text input and a Submit button which when clicked, updates the value of the
AthleteColumn cell in the hovered row and then closes itself by callinghideTooltipCallback().
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
RowApiModule,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import CustomTooltip from "./customTooltip.tsx";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule, RowApiModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
field: "athlete",
minWidth: 150,
tooltip: true,
tooltipComponentParams: { type: "success" },
},
{ field: "age", minWidth: 130, tooltip: true },
{ field: "year" },
{ field: "sport" },
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
tooltipComponent: CustomTooltip,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipInteraction={true}
tooltipShowDelay={500}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.custom-tooltip {
color: var(--ag-foreground-color);
background-color: #5577cc;
padding: 5px;
}
.custom-tooltip p,
.custom-tooltip h3 {
margin: 5px;
white-space: nowrap;
}
.custom-tooltip p:first-of-type {
font-weight: bold;
}
import React, { useMemo, useRef } from 'react';
import type { CustomTooltipProps } from 'ag-grid-react';
export default (props: CustomTooltipProps & { type: string }) => {
const data = useMemo(() => props.api.getDisplayedRowAtIndex(props.rowIndex!)!.data, []);
const inputEl = useRef<HTMLInputElement>(null);
const onFormSubmit = (e: any) => {
e.preventDefault();
const { node } = props;
const target = inputEl.current as HTMLInputElement;
if (target.value && node) {
node.setDataValue('athlete', target.value);
if (props.hideTooltipCallback) {
props.hideTooltipCallback();
}
}
};
return (
<div className="custom-tooltip">
<div className={'panel panel-' + (props.type || 'primary')}>
<div className="panel-heading">
<h3 className="panel-title">{data.country}</h3>
</div>
<form className="panel-body" onSubmit={onFormSubmit}>
<div className="form-group">
<input
type="text"
ref={inputEl}
className="form-control"
id="name"
placeholder="Name"
autoComplete="off"
defaultValue={data.athlete}
onFocus={(e) => e.target.select()}
/>
<button type="submit" className="btn btn-primary">
Submit
</button>
</div>
<p>Total: {data.total}</p>
</form>
</div>
</div>
);
};
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; Custom Component Copy Link
The grid does not use the browser's default tooltip, instead it has a rich HTML Tooltip Component. The default Tooltip Component can be replaced with a Custom Tooltip Component using colDef.tooltipComponent.
In the example below:
tooltipComponentis set on the Default Column Definition so it applies to all Columns.tooltipComponentParamsis set on the Athlete Column Definition to provide a Custom Property, in this instance setting the background color.
"use client";
import React, {
useCallback,
useMemo,
useRef,
useState,
StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
GridApi,
GridOptions,
ModuleRegistry,
TooltipModule,
enableDevValidations,
} from "ag-grid-community";
import CustomTooltip from "./customTooltip.tsx";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [TooltipModule, ClientSideRowModelModule];
const GridExample = () => {
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{
headerName: "Athlete",
field: "athlete",
tooltipComponentParams: { color: "#55AA77" },
tooltip: ({ data }) => data?.country,
headerTooltip: "Tooltip for Athlete Column Header",
},
{
field: "age",
tooltip: "Create any fixed message, e.g. This is the Athlete’s Age ",
headerTooltip: "Tooltip for Age Column Header",
},
{
field: "year",
tooltip: (p) => "This is a dynamic tooltip using the value of " + p.value,
headerTooltip: "Tooltip for Year Column Header",
},
{
field: "sport",
tooltip: "Tooltip text about Sport should go here",
headerTooltip: "Tooltip for Sport Column Header",
},
]);
const defaultColDef = useMemo<ColDef>(() => {
return {
flex: 1,
minWidth: 100,
tooltipComponent: CustomTooltip,
};
}, []);
const { data, loading } = useFetchJson<IOlympicData>(
"https://www.ag-grid.com/example-assets/olympic-winners.json",
);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div style={gridStyle}>
<AgGridReact<IOlympicData>
rowData={data}
loading={loading}
columnDefs={columnDefs}
defaultColDef={defaultColDef}
tooltipShowDelay={0}
tooltipHideDelay={2000}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.custom-tooltip {
padding: 5px;
color: var(--ag-foreground-color);
background-color: #5577cc;
}
.custom-tooltip p {
margin: 5px;
white-space: nowrap;
}
.custom-tooltip p:first-of-type {
font-weight: bold;
}
import React, { useMemo } from 'react';
import type { CustomTooltipProps } from 'ag-grid-react';
export default (props: CustomTooltipProps & { color: string }) => {
return (
<div className="custom-tooltip" style={{ backgroundColor: props.color || '#999' }}>
<div>
<b>Custom Tooltip</b>
</div>
<div>{props.value}</div>
</div>
);
};
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} import { useState, useEffect } from 'react';
/**
* Fetch example Json data
* Not recommended for production use!
*/
export const useFetchJson = <T,>(url:string, limit?: number) => {
const [data, setData] = useState<T[]>();
const [loading, setLoading] = useState(true);
useEffect(() => {
// StrictMode runs this effect twice: drop the superseded run's response rather than applying both.
let cancelled = false;
const fetchData = async () => {
setLoading(true);
// Note error handling is omitted here for brevity
const response = await fetch(url);
const json = await response.json();
const data = limit ? json.slice(0, limit) : json;
if (cancelled) {
return;
}
setData(data);
setLoading(false);
};
fetchData();
return () => {
cancelled = true;
};
}, [url, limit]);
return { data, loading };
}; When a tooltip component is instantiated then the following will be made available on props:
Properties available on the CustomTooltipProps<TData = any, TValue = any, TContext = any> interface.
The resolved value to render in the tooltip. |
A callback function that hides the tooltip. |
What part of the application is showing the tooltip, e.g. 'cell', 'header', or 'menu'. |
The formatted source value, when available. |
Column / ColumnGroup definition. |
Column / ColumnGroup |
The index of the row containing the cell rendering the tooltip. |
The row node. |
Data for the row node in question. |
The grid api. |
Application context as set on gridOptions.context. |