Custom Tool Panel Components can be included into the grid's Side Bar. Implement these when you require more Tool Panels to meet your application requirements.
The example below provides a 'Custom Stats' Tool Panel to demonstrates how to create and register a Custom Tool Panel Component with the grid and include it the Side Bar:
import { Component } from "@angular/core";
import { HttpClient } from "@angular/common/http";
import { AgGridAngular } from "ag-grid-angular";
import {
CellValueChangedEvent,
ClientSideRowModelApiModule,
ClientSideRowModelModule,
ColDef,
ColGroupDef,
EventApiModule,
GridApi,
GridOptions,
GridReadyEvent,
Icons,
ModuleRegistry,
NumberEditorModule,
NumberFilterModule,
RowApiModule,
SideBarDef,
TextEditorModule,
TextFilterModule,
Theme,
enableDevValidations,
iconOverrides,
themeQuartz,
} from "ag-grid-community";
import {
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
} from "ag-grid-enterprise";
if (process.env.NODE_ENV !== "production") {
// Enable extended validations only for development
enableDevValidations();
}
ModuleRegistry.registerModules([
ClientSideRowModelApiModule,
NumberEditorModule,
TextEditorModule,
NumberFilterModule,
ClientSideRowModelModule,
ColumnsToolPanelModule,
FiltersToolPanelModule,
SetFilterModule,
TextFilterModule,
RowApiModule,
EventApiModule,
]);
import { CustomStatsToolPanel } from "./custom-stats-tool-panel.component";
import { IOlympicData } from "./interfaces";
@Component({
selector: "my-app",
standalone: true,
imports: [AgGridAngular, CustomStatsToolPanel],
template: `<div style="height: 100%; box-sizing: border-box">
<ag-grid-angular
style="width: 100%; height: 100%;"
[columnDefs]="columnDefs"
[theme]="theme"
[defaultColDef]="defaultColDef"
[icons]="icons"
[sideBar]="sideBar"
[rowData]="rowData"
(cellValueChanged)="onCellValueChanged($event)"
(gridReady)="onGridReady($event)"
/>
</div> `,
})
export class AppComponent {
columnDefs: ColDef[] = [
{ field: "athlete", width: 150, filter: "agTextColumnFilter" },
{ field: "age", width: 90 },
{ field: "country", width: 120 },
{ field: "year", width: 90 },
{ field: "date", width: 110 },
{ field: "gold", width: 100, filter: false },
{ field: "silver", width: 100, filter: false },
{ field: "bronze", width: 100, filter: false },
{ field: "total", width: 100, filter: false },
];
theme: Theme | "legacy" = themeQuartz.withPart(
iconOverrides({
type: "image",
mask: true,
icons: {
// map of icon names to images
"custom-stats": {
svg: '<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16"><g stroke="#7F8C8D" fill="none" fill-rule="evenodd"><path d="M10.5 6V4.5h-5v.532a1 1 0 0 0 .36.768l1.718 1.432a1 1 0 0 1 0 1.536L5.86 10.2a1 1 0 0 0-.36.768v.532h5V10"/><rect x="1.5" y="1.5" width="13" height="13" rx="2"/></g></svg>',
},
},
}),
);
defaultColDef: ColDef = {
editable: true,
flex: 1,
minWidth: 100,
filter: true,
};
icons: Icons = {
"custom-stats": '<span class="ag-icon ag-icon-custom-stats"></span>',
};
sideBar: SideBarDef | string | string[] | boolean | null = {
toolPanels: [
{
id: "columns",
labelDefault: "Columns",
labelKey: "columns",
iconKey: "columns",
toolPanel: "agColumnsToolPanel",
},
{
id: "filters",
labelDefault: "Filters",
labelKey: "filters",
iconKey: "filter",
toolPanel: "agFiltersToolPanel",
},
{
id: "customStats",
labelDefault: "Custom Stats",
labelKey: "customStats",
iconKey: "custom-stats",
toolPanel: CustomStatsToolPanel,
toolPanelParams: {
title: "Custom Stats",
},
},
],
defaultToolPanel: "customStats",
};
rowData!: IOlympicData[];
constructor(private http: HttpClient) {}
onCellValueChanged(params: CellValueChangedEvent) {
params.api.refreshClientSideRowModel();
}
onGridReady(params: GridReadyEvent<IOlympicData>) {
this.http
.get<
IOlympicData[]
>("https://www.ag-grid.com/example-assets/olympic-winners.json")
.subscribe((data) => {
this.rowData = data;
});
}
}
import { ChangeDetectionStrategy, Component, signal } from '@angular/core';
import type { IToolPanelAngularComp } from 'ag-grid-angular';
import type { IRowNode, IToolPanelParams } from 'ag-grid-community';
export interface CustomStatsToolPanelParams extends IToolPanelParams {
title: string;
}
@Component({
standalone: true,
changeDetection: ChangeDetectionStrategy.OnPush,
template: ` <div style="text-align: center">
<span>
<h2><i class="fa fa-calculator"></i> {{ title() }}</h2>
<dl style="font-size: large; padding: 30px 40px 10px 30px">
<dt class="totalStyle">
Total Medals: <b>{{ numMedals() }}</b>
</dt>
<dt class="totalStyle">
Total Gold: <b>{{ numGold() }}</b>
</dt>
<dt class="totalStyle">
Total Silver: <b>{{ numSilver() }}</b>
</dt>
<dt class="totalStyle">
Total Bronze: <b>{{ numBronze() }}</b>
</dt>
</dl>
</span>
</div>`,
styles: [
`
.totalStyle {
padding-bottom: 15px;
}
`,
],
})
export class CustomStatsToolPanel implements IToolPanelAngularComp {
private params!: CustomStatsToolPanelParams;
numMedals = signal(0);
numGold = signal(0);
numSilver = signal(0);
numBronze = signal(0);
title = signal('');
agInit(params: CustomStatsToolPanelParams): void {
this.params = params;
this.title.set(params.title);
// calculate stats when new rows loaded, i.e. onModelUpdated
this.params.api.addEventListener('modelUpdated', this.updateTotals.bind(this));
}
updateTotals(): void {
let numGold = 0,
numSilver = 0,
numBronze = 0;
this.params.api.forEachNode((rowNode: IRowNode) => {
const data = rowNode.data;
if (data.gold) numGold += data.gold;
if (data.silver) numSilver += data.silver;
if (data.bronze) numBronze += data.bronze;
});
this.numMedals.set(numGold + numSilver + numBronze);
this.numGold.set(numGold);
this.numSilver.set(numSilver);
this.numBronze.set(numBronze);
}
refresh(): void {}
}
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()],
});
export interface IOlympicData {
athlete: string,
age: number,
country: string,
year: number,
date: string,
sport: string,
gold: number,
silver: number,
bronze: number,
total: number
} Implementing a Tool Panel Component Copy Link
Implement this interface to create a tool panel component.
interface IToolPanelAngularComp {
// mandatory methods
// The agInit(params) method is called on the tool panel component once.
// See below for details on the parameters.
agInit(params: IToolPanelParams): void;
// optional methods
// Called when `api.refreshToolPanel()` is called (with the current params).
// Also called when the `sideBar` grid option is updated, and when `api.setState`
// restores side bar state (with the updated params).
// When `sideBar` is updated or state is restored, if this method returns `true`,
// then the grid will take no further action.
// Otherwise, the tool panel will be destroyed and recreated.
refresh(params: IToolPanelParams): boolean | void;
// If saving and restoring state, this should return the current state
getState(): any;
}The agInit(params) method takes a params object with the items listed below:
Properties available on the IToolPanelParams<TData = any, TContext = any, TState = any> interface.
If tool panel is saving and restoring state, this should be called after the state is updated |
The tool panel state to apply, if applicable. Provided from initialState in the grid options, and again with each api.setState restore that includes side bar state.
|
The grid api. |
Application context as set on gridOptions.context. |
Registering Tool Panel Components Copy Link
Registering a Tool Panel component follows the same approach as any other custom components in the grid. For more details see: Registering Custom Components.
Once the Tool Panel Component is registered with the grid it needs to be included into the Side Bar. The following snippet illustrates this:
sideBar: {
toolPanels: [
{
id: 'customStats',
labelDefault: 'Custom Stats',
labelKey: 'customStats',
iconKey: 'custom-stats',
toolPanel: CustomStatsComponent,
toolPanelParams: {
// can pass any custom params here
},
}
]
}
// other grid propertiesFor more details on the configuration properties above, refer to the Side Bar Configuration section.