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.
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import type { ColDef, GridApi, GridReadyEvent } from "ag-grid-community";
import {
ClientSideRowModelModule,
ColumnApiModule,
ModuleRegistry,
enableDevValidations,
} from "ag-grid-community";
import { getData } from "./data";
import "./styles.css";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([ColumnApiModule, ClientSideRowModelModule]);
@Component({
standalone: true,
imports: [AgGridAngular],
selector: "my-app",
template: `
<div class="test-container">
<div class="test-header">
<div style="margin-bottom: 1rem;">
<input type="checkbox" id="pinFirstColumnOnLoad" />
<label for="pinFirstColumnOnLoad">Pin first column on load</label>
</div>
<div style="margin-bottom: 1rem;">
<button id="reloadGridButton" (click)="reloadGrid()">
Reload Grid
</button>
</div>
</div>
@if (isVisible) {
<ag-grid-angular
style="width: 100%; height: 100%;"
[columnDefs]="columnDefs"
[rowData]="rowData"
(gridReady)="onGridReady($event)"
/>
}
</div>
`,
})
export class AppComponent {
public isVisible = true;
private gridApi!: GridApi;
public columnDefs: 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" },
];
public rowData: any[] | null = getData();
reloadGrid() {
this.isVisible = false;
setTimeout(() => (this.isVisible = true), 1);
}
onGridReady(params: GridReadyEvent) {
this.gridApi = params.api;
const checkbox = document.querySelector<HTMLInputElement>(
"#pinFirstColumnOnLoad",
)!;
const shouldPinFirstColumn = checkbox && checkbox.checked;
if (shouldPinFirstColumn) {
params.api.applyColumnState({
state: [{ colId: "name", pinned: "left" }],
});
}
}
}
.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,
},
},
];
}
import '@angular/compiler';
import { provideHttpClient } from '@angular/common/http';
import { enableProdMode } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
if (new URLSearchParams(window.location.search).get('prod') !== 'false') {
enableProdMode();
}
const app = bootstrapApplication(AppComponent, {
providers: [provideHttpClient()],
});
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.
import { Component } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
import "./styles.css";
import {
ClientSideRowModelModule,
ColDef,
ColGroupDef,
FirstDataRenderedEvent,
GridApi,
GridOptions,
GridReadyEvent,
ModuleRegistry,
RowDataUpdatedEvent,
enableDevValidations,
} from "ag-grid-community";
import { TAthlete, fetchDataAsync } from "./data";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([ClientSideRowModelModule]);
@Component({
selector: "my-app",
standalone: true,
imports: [AgGridAngular],
template: `<div class="test-container">
<div class="test-header">
<div id="firstDataRendered">
First Data Rendered: <span class="value">-</span>
</div>
<div id="rowDataUpdated">
Row Data Updated: <span class="value">-</span>
</div>
<div>
<button id="btnReloadData" (click)="onBtnReloadData()">
Reload Data
</button>
</div>
</div>
<ag-grid-angular
style="width: 100%; height: 100%;"
[columnDefs]="columnDefs"
[loading]="true"
[rowData]="rowData"
(firstDataRendered)="onFirstDataRendered($event)"
(rowDataUpdated)="onRowDataUpdated($event)"
(gridReady)="onGridReady($event)"
/>
</div> `,
})
export class AppComponent {
private gridApi!: GridApi;
columnDefs: ColDef[] = [
{ field: "name", headerName: "Athlete" },
{ field: "person.age", headerName: "Age" },
{ field: "medals.gold", headerName: "Gold Medals" },
];
rowData!: any[];
onFirstDataRendered(event: FirstDataRenderedEvent) {
updateRowCount("firstDataRendered");
console.log("First Data Rendered");
}
onRowDataUpdated(event: RowDataUpdatedEvent<TAthlete>) {
updateRowCount("rowDataUpdated");
console.log("Row Data Updated");
}
onBtnReloadData() {
console.log("Reloading Data ...");
setBtnReloadDataDisabled(true);
this.gridApi.setGridOption("loading", true);
fetchDataAsync()
.then((data) => {
console.log("Data Reloaded");
this.gridApi.setGridOption("rowData", data);
})
.catch((error) => {
console.error("Failed to reload data", error);
})
.finally(() => {
this.gridApi.setGridOption("loading", false);
setBtnReloadDataDisabled(false);
});
}
onGridReady(params: GridReadyEvent) {
this.gridApi = params.api;
console.log("Loading Data ...");
fetchDataAsync()
.then((data) => {
console.log("Data Loaded");
params.api!.setGridOption("rowData", data);
})
.catch((error) => {
console.error("Failed to load data", error);
})
.finally(() => {
params.api!.setGridOption("loading", false);
setBtnReloadDataDisabled(false);
});
}
}
const updateRowCount = (id: string) => {
const element = document.querySelector(`#${id} > .value`);
element!.textContent = `${new Date().toLocaleTimeString()}`;
};
const setBtnReloadDataDisabled = (disabled: boolean) => {
(document.getElementById("btnReloadData") as HTMLButtonElement).disabled =
disabled;
};
.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),
};
}
import '@angular/compiler';
import { provideHttpClient } from '@angular/common/http';
import { enableProdMode } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { AppComponent } from './app.component';
if (new URLSearchParams(window.location.search).get('prod') !== 'false') {
enableProdMode();
}
const app = bootstrapApplication(AppComponent, {
providers: [provideHttpClient()],
});
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.
Angular PreDestroy Setup Copy Link
When using Angular, the gridPreDestroyed event handler must be registered via grid options instead of as an Output event handler to work correctly.
For example:
this.gridOptions = {
onGridPreDestroyed: () => {
// handler code
}
};