This section covers some common lifecycle events that are raised after grid initialisation, data updates, and before the grid is destroyed.
The events on this page are listed in the order they are raised.
Grid Ready Copy Link
The gridReady event fires upon grid initialisation but the grid may not be fully rendered.
Common Uses
- Customising Grid via API calls.
- Event listener setup.
- Grid-dependent setup code.
In this example, gridReady applies user pinning preferences before rendering data.
'use client';
import React, {
StrictMode,
useCallback,
useMemo,
useRef,
useState,
} from "react";
import { createRoot } from "react-dom/client";
import type { ColDef, GridReadyEvent } from "ag-grid-community";
import {
ClientSideRowModelModule,
ColumnApiModule,
enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";
import { getData } from "./data";
import "./styles.css";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [ColumnApiModule, ClientSideRowModelModule];
const GridExample = () => {
const gridRef = useRef<AgGridReact>(null);
const [gridKey, setGridKey] = useState<string>(`grid-key-${window.agRandom()}`);
const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
const [rowData, setRowData] = useState<any[]>(getData());
const [columnDefs, setColumnDefs] = useState<ColDef[]>([
{ field: "name", headerName: "Athlete", width: 250 },
{ field: "person.country", headerName: "Country" },
{ field: "person.age", headerName: "Age" },
{ field: "medals.gold", headerName: "Gold Medals" },
{ field: "medals.silver", headerName: "Silver Medals" },
{ field: "medals.bronze", headerName: "Bronze Medals" },
]);
const onGridReady = useCallback((params: GridReadyEvent) => {
const checkbox = document.querySelector<HTMLInputElement>(
"#pinFirstColumnOnLoad",
)!;
const shouldPinFirstColumn = checkbox && checkbox.checked;
if (shouldPinFirstColumn) {
params.api.applyColumnState({
state: [{ colId: "name", pinned: "left" }],
});
}
}, []);
const reloadGrid = useCallback(() => {
// Trigger re-load by assigning a new key to the Grid React component
setGridKey(`grid-key-${window.agRandom()}`);
}, []);
return (
<AgGridProvider modules={modules}>
<div style={containerStyle}>
<div className="test-container">
<div className="test-header">
<div style={{ marginBottom: "1rem" }}>
<input type="checkbox" id="pinFirstColumnOnLoad" />
<label htmlFor="pinFirstColumnOnLoad">
Pin first column on load
</label>
</div>
<div style={{ marginBottom: "1rem" }}>
<button id="reloadGridButton" onClick={reloadGrid}>
Reload Grid
</button>
</div>
</div>
<div style={gridStyle}>
<AgGridReact
key={gridKey}
ref={gridRef}
rowData={rowData}
columnDefs={columnDefs}
onGridReady={onGridReady}
/>
</div>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.test-grid {
flex-grow: 1;
}
.test-container {
height: 100%;
display: flex;
flex-direction: column;
}
.test-header {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
margin-bottom: 1rem;
}
export interface TAthlete {
name: string;
medals: {
gold: number;
silver: number;
bronze: number;
};
person: {
age: number;
country: string;
};
}
export function getData(): TAthlete[] {
return [
{
name: "Michael Phelps",
person: {
age: 23,
country: "United States",
},
medals: {
gold: 8,
silver: 0,
bronze: 0,
},
},
{
name: "Michael Phelps",
person: {
age: 19,
country: "United States",
},
medals: {
gold: 6,
silver: 0,
bronze: 2,
},
},
{
name: "Michael Phelps",
person: {
age: 27,
country: "United States",
},
medals: {
gold: 4,
silver: 2,
bronze: 0,
},
},
{
name: "Natalie Coughlin",
person: {
age: 25,
country: "United States",
},
medals: {
gold: 1,
silver: 2,
bronze: 3,
},
},
{
name: "Aleksey Nemov",
person: {
age: 24,
country: "Russia",
},
medals: {
gold: 2,
silver: 1,
bronze: 3,
},
},
{
name: "Alicia Coutts",
person: {
age: 24,
country: "Australia",
},
medals: {
gold: 1,
silver: 3,
bronze: 1,
},
},
{
name: "Missy Franklin",
person: {
age: 17,
country: "United States",
},
medals: {
gold: 4,
silver: 0,
bronze: 1,
},
},
{
name: "Ryan Lochte",
person: {
age: 27,
country: "United States",
},
medals: {
gold: 2,
silver: 2,
bronze: 1,
},
},
{
name: "Allison Schmitt",
person: {
age: 22,
country: "United States",
},
medals: {
gold: 3,
silver: 1,
bronze: 1,
},
},
{
name: "Natalie Coughlin",
person: {
age: 21,
country: "United States",
},
medals: {
gold: 2,
silver: 2,
bronze: 1,
},
},
{
name: "Ian Thorpe",
person: {
age: 17,
country: "Australia",
},
medals: {
gold: 3,
silver: 2,
bronze: 0,
},
},
{
name: "Dara Torres",
person: {
age: 33,
country: "United States",
},
medals: {
gold: 2,
silver: 0,
bronze: 3,
},
},
{
name: "Cindy Klassen",
person: {
age: 26,
country: "Canada",
},
medals: {
gold: 1,
silver: 2,
bronze: 2,
},
},
{
name: "Nastia Liukin",
person: {
age: 18,
country: "United States",
},
medals: {
gold: 1,
silver: 3,
bronze: 1,
},
},
{
name: "Marit Bjørgen",
person: {
age: 29,
country: "Norway",
},
medals: {
gold: 3,
silver: 1,
bronze: 1,
},
},
{
name: "Sun Yang",
person: {
age: 20,
country: "China",
},
medals: {
gold: 2,
silver: 1,
bronze: 1,
},
},
{
name: "Kirsty Coventry",
person: {
age: 24,
country: "Zimbabwe",
},
medals: {
gold: 1,
silver: 3,
bronze: 0,
},
},
{
name: "Libby Lenton-Trickett",
person: {
age: 23,
country: "Australia",
},
medals: {
gold: 2,
silver: 1,
bronze: 1,
},
},
{
name: "Ryan Lochte",
person: {
age: 24,
country: "United States",
},
medals: {
gold: 2,
silver: 0,
bronze: 2,
},
},
{
name: "Inge de Bruijn",
person: {
age: 30,
country: "Netherlands",
},
medals: {
gold: 1,
silver: 1,
bronze: 2,
},
},
];
}
First Data Rendered Copy Link
The firstDataRendered event fires the first time data is rendered into the grid. It will only be fired once unlike rowDataUpdated which is fired on every data change.
Row Data Updated Copy Link
The rowDataUpdated event fires every time the grid's data changes, by Updating Row Data or by applying Transaction Updates. In the Server Side Row Model, use the Model Updated Event instead.
In this example the time at which firstDataRendered and rowDataUpdated are fired is recorded above the grid. Note that firstDataRendered is only set on the initial load of the grid and is not updated when reloading data.
'use client';
import React, { StrictMode, useCallback, useEffect, useState } from "react";
import { createRoot } from "react-dom/client";
import {
ClientSideRowModelModule,
enableDevValidations,
} from "ag-grid-community";
import type {
FirstDataRenderedEvent,
RowDataUpdatedEvent,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";
import { fetchDataAsync } from "./data";
import type { TAthlete } from "./data";
import "./styles.css";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
const modules = [ClientSideRowModelModule];
const updateRowCount = (id: string) => {
const element = document.querySelector(`#${id} > .value`);
element!.textContent = `${new Date().toLocaleTimeString()}`;
};
const columnDefs = [
{ field: "name", headerName: "Athlete" },
{ field: "person.age", headerName: "Age" },
{ field: "medals.gold", headerName: "Gold Medals" },
];
const GridExample = () => {
const [loading, setLoading] = useState<boolean>(true);
const [rowData, setRowData] = useState<TAthlete[] | undefined>();
const onFirstDataRendered = useCallback((event: FirstDataRenderedEvent) => {
updateRowCount("firstDataRendered");
console.log("First Data Rendered");
}, []);
const onRowDataUpdated = useCallback(
(event: RowDataUpdatedEvent<TAthlete>) => {
updateRowCount("rowDataUpdated");
console.log("Row Data Updated");
},
[],
);
const reloadData = useCallback(() => {
console.log("Loading Data ...");
setLoading(true);
fetchDataAsync()
.then((data) => {
console.info("Data Loaded");
setRowData(data);
})
.catch((error) => {
console.error("Failed to load data", error);
})
.finally(() => {
setLoading(false);
});
}, []);
useEffect(reloadData, []);
return (
<AgGridProvider modules={modules}>
<div className="test-container">
<div className="test-header">
<div id="firstDataRendered">
First Data Rendered: <span className="value">-</span>
</div>
<div id="rowDataUpdated">
Row Data Updated: <span className="value">-</span>
</div>
<div>
<button disabled={loading} onClick={reloadData}>
Reload Data
</button>
</div>
</div>
<div style={{ height: "100%" }}>
<AgGridReact
loading={loading}
rowData={rowData}
columnDefs={columnDefs}
onFirstDataRendered={onFirstDataRendered}
onRowDataUpdated={onRowDataUpdated}
/>
</div>
</div>
</AgGridProvider>
);
};
const root = createRoot(document.getElementById("root")!);
root.render(
<StrictMode>
<GridExample />
</StrictMode>,
);
.test-grid {
flex-grow: 1;
}
.test-container {
height: 100%;
display: flex;
flex-direction: column;
}
.test-header {
font-family: Verdana, Geneva, Tahoma, sans-serif;
font-size: 13px;
}
.test-header button[disabled] {
opacity: 0.7;
}
.test-header > div {
margin-bottom: 1rem;
}
export interface TAthlete {
name: string;
medals: {
gold: number;
silver: number;
bronze: number;
};
person: {
age: number;
country: string;
};
}
export function fetchDataAsync(): Promise<TAthlete[]> {
// Simulate a slow network request
return new Promise((resolve) => {
setTimeout(() => {
resolve([
{
name: "Michael Phelps",
person: { age: 23, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Michael Phelps",
person: { age: 19, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Michael Phelps",
person: { age: 27, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Natalie Coughlin",
person: { age: 25, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Aleksey Nemov",
person: { age: 24, country: "Russia" },
medals: getRandomMedals(),
},
{
name: "Alicia Coutts",
person: { age: 24, country: "Australia" },
medals: getRandomMedals(),
},
{
name: "Missy Franklin",
person: { age: 17, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Ryan Lochte",
person: { age: 27, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Allison Schmitt",
person: { age: 22, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Natalie Coughlin",
person: { age: 21, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Ian Thorpe",
person: { age: 17, country: "Australia" },
medals: getRandomMedals(),
},
{
name: "Dara Torres",
person: { age: 33, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Cindy Klassen",
person: { age: 26, country: "Canada" },
medals: getRandomMedals(),
},
{
name: "Nastia Liukin",
person: { age: 18, country: "United States" },
medals: getRandomMedals(),
},
{
name: "Marit Bjørgen",
person: { age: 29, country: "Norway" },
medals: getRandomMedals(),
},
{
name: "Sun Yang",
person: { age: 20, country: "China" },
medals: getRandomMedals(),
},
]);
}, 600);
});
}
function getRandomMedals() {
return {
gold: Math.floor(window.agRandom() * 10),
silver: Math.floor(window.agRandom() * 10),
bronze: Math.floor(window.agRandom() * 10),
};
}
Grid Pre-Destroyed Copy Link
The gridPreDestroyed event fires just before the grid is destroyed and is removed from the DOM.
Common Uses
- Clean up resources.
- Save grid state.
- Disconnect other libraries.
The Grid State Example demonstrates how gridPreDestroyed can be used to save and restore grid state.