---
product: "AG Grid"
title: "Tool Panel Component"
description: "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."
enterprise: true
framework: angular
version: "36.2.0"
related:
    - title: "Side Bar"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/side-bar/"
    - title: "Columns Tool Panel"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/tool-panel-columns/"
    - title: "Filters Tool Panel (New)"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/tool-panel-filters-new/"
    - title: "Filters Tool Panel"
      url: "https://www.ag-grid.com/archive/36.2.0/angular-data-grid/tool-panel-filters/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Tool Panel Component

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:

#### Custom Stats

```ts
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;
      });
  }
}
```

[Live example: Custom Stats](https://www.ag-grid.com/archive/36.2.0/examples/component-tool-panel/custom-stats/angular/)

## Implementing a Tool Panel Component

Implement this interface to create a tool panel component.

```ts
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&lt;TData = any, TContext = any, TState = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `onStateUpdated` | `Function` |  |  |  |
| `initialState` | `TState` |  |  |  |
| `api` | `GridApi` |  |  |  |
| `context` | `TContext` |  |  |  |

## Registering Tool Panel Components

Registering a Tool Panel component follows the same approach as any other custom components in the grid. For more details see: [Registering Custom Components](https://www.ag-grid.com/archive/36.2.0/angular-data-grid/components/#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:

```js
    sideBar: {
        toolPanels: [
            {
                id: 'customStats',
                labelDefault: 'Custom Stats',
                labelKey: 'customStats',
                iconKey: 'custom-stats',
                toolPanel: CustomStatsComponent,
                toolPanelParams: {
                    // can pass any custom params here
                },
            }
        ]
    }
    // other grid properties
```

For more details on the configuration properties above, refer to the [Side Bar Configuration](https://www.ag-grid.com/archive/36.2.0/angular-data-grid/side-bar/#sidebardef-configuration) section.
