---
title: "Tool Panel Component"
enterprise: true
framework: vue
version: "36.1.0"
---

# 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 {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
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";
import CustomStatsToolPanel from "./customStatsToolPanelVue";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelApiModule,
  NumberEditorModule,
  TextEditorModule,
  NumberFilterModule,
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  SetFilterModule,
  TextFilterModule,
  RowApiModule,
  EventApiModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div style="height: 100%; box-sizing: border-box">
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :theme="theme"
        :defaultColDef="defaultColDef"
        :icons="icons"
        :sideBar="sideBar"
        :rowData="rowData"
        @cell-value-changed="onCellValueChanged"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    CustomStatsToolPanel,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<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 },
    ]);
    const theme = ref<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>',
            },
          },
        }),
      ),
    );
    const defaultColDef = ref<ColDef>({
      editable: true,
      flex: 1,
      minWidth: 100,
      filter: true,
    });
    const icons = ref<Icons>({
      "custom-stats": '<span class="ag-icon ag-icon-custom-stats"></span>',
    });
    const sideBar = ref<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",
    });
    const rowData = ref<IOlympicData[]>(null);

    function onCellValueChanged(params: CellValueChangedEvent) {
      params.api.refreshClientSideRowModel();
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      theme,
      defaultColDef,
      icons,
      sideBar,
      rowData,
      onGridReady,
      onCellValueChanged,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

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

## Implementing a Tool Panel Component

Any valid Vue component can be a tool panel component, however it is also possible to implement the following optional methods:

```ts
interface IToolPanel {
    // Called when `api.refreshToolPanel()` is called (with the current params).
    // Also called when the `sideBar` grid option is updated (with the updated params).
    // When `sideBar` is updated, 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;
}
```

When a custom tool panel component is instantiated then the following will be made available on `this.params`:

Properties available on the `IToolPanelParams&lt;TData = any, TContext = any, TState = any&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `onStateUpdated` | `Function` |  |  | If tool panel is saving and restoring state, this should be called after the state is updated |
| `initialState` | `TState` |  |  | The tool-panel-specific initial state as provided in grid options if applicable |
| `api` | [`GridApi`](https://www.ag-grid.com/vue-data-grid/grid-api/) |  |  | The grid api. |
| `context` | [`TContext`](https://www.ag-grid.com/vue-data-grid/typescript-generics/#context-tcontext) |  |  | Application context as set on `gridOptions.context`. |

## 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/vue-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
this.gridOptions: {
    sideBar: {
        toolPanels: [
            {
                id: 'customStats',
                labelDefault: 'Custom Stats',
                labelKey: 'customStats',
                iconKey: 'custom-stats',
                toolPanel: 'customStatsToolPanel',
                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/vue-data-grid/side-bar/#sidebardef-configuration) section.
