---
title: "Filters Tool Panel"
enterprise: true
framework: react
version: "36.1.0"
---

# Filters Tool Panel

The **Filters Tool Panel** allows accessing the grid's filters without needing to open up the column menu.

> **Note**
>
> Consider using the [New Filters Tool Panel](https://www.ag-grid.com/react-data-grid/tool-panel-filters-new/) instead, which provides improved UX.

The example below shows the Filters Tool Panel. The following can be noted:

- Columns Athlete, Age, Country, Year and Date appear in the Filters Tool Panel as they have filters.
- Columns Gold, Silver, Bronze and Total do not appear in the Filters Tool Panel as they have no filters.
- Clicking on a column in the Filters Tool Panel will show the filter below the column name. Clicking a second time will hide the filter again.
- Columns with filters active will have the filter icon appear beside the filter name in the tool panel.

#### Filters Tool Panel

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  NumberFilterModule,
  ClientSideRowModelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
  TextFilterModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", minWidth: 200, filter: "agTextColumnFilter" },
    { field: "age" },
    { field: "country", minWidth: 200 },
    { field: "year" },
    { field: "date", minWidth: 180 },
    { field: "gold", filter: false },
    { field: "silver", filter: false },
    { field: "bronze", filter: false },
    { field: "total", filter: false },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            sideBar={"filters"}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Filters Tool Panel](https://www.ag-grid.com/examples/tool-panel-filters/simple/reactFunctionalTs)

## Suppress Options

It is possible to remove items from the Filters Tool Panel. Items are suppressed by setting one or more of the following `toolPanelParams` to `true` when you are using the `agFiltersToolPanel` component:

Properties available on the `IToolPanelFiltersCompParams` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressExpandAll` | `boolean` |  |  | To suppress Expand / Collapse All |
| `suppressFilterSearch` | `boolean` |  |  | To suppress the Filter Search |
| `suppressSyncLayoutWithGrid` | `boolean` |  |  | Suppress updating the layout of columns as they are rearranged in the grid |

To remove a particular column / filter from the tool panel, set the column property `suppressFiltersToolPanel` to `true`.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `suppressFiltersToolPanel` | `boolean` |  | `false` | Set to `true` if you do not want this column (filter) or group (filter group) to appear in the Filters Tool Panel. Module: [`ColumnsToolPanelModule`](https://www.ag-grid.com/react-data-grid/modules/). |

The example below demonstrates the suppress options described above. Note the following:

- **Expand / Collapse All** and **Filter Search** are hidden as `suppressExpandAll` and `suppressFilterSearch` are both set to `true`.
- The date column / filter is hidden from the tool panel using: `colDef.suppressFiltersToolPanel=true`.

#### Suppress Options

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  NumberFilterModule,
  ClientSideRowModelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
  TextFilterModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
    {
      groupId: "athleteGroupId",
      headerName: "Athlete",
      children: [
        {
          headerName: "Name",
          field: "athlete",
          minWidth: 200,
          filter: "agTextColumnFilter",
        },
        { field: "age" },
        {
          groupId: "competitionGroupId",
          headerName: "Competition",
          children: [
            { field: "year" },
            { field: "date", minWidth: 180, suppressFiltersToolPanel: true },
          ],
        },
        { field: "country", minWidth: 200 },
      ],
    },
    { colId: "sport", field: "sport", minWidth: 200 },
    {
      headerName: "Medals",
      children: [
        { field: "gold" },
        { field: "silver" },
        { field: "bronze" },
        { field: "total" },
      ],
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
    };
  }, []);
  const sideBar = useMemo<
    SideBarDef | string | string[] | boolean | null
  >(() => {
    return {
      toolPanels: [
        {
          id: "filters",
          labelDefault: "Filters",
          labelKey: "filters",
          iconKey: "filter",
          toolPanel: "agFiltersToolPanel",
          toolPanelParams: {
            suppressExpandAll: true,
            suppressFilterSearch: true,
          },
        },
      ],
      defaultToolPanel: "filters",
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            sideBar={sideBar}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Suppress Options](https://www.ag-grid.com/examples/tool-panel-filters/suppress-options/reactFunctionalTs)

## Filter Instances

The filters provided in the tool panel are the same instances as the filter in the column menu. This has the following implications:

- Configuration relating to filters equally applies when the filters appear in the tool panel.
- The filter behaves exactly as when it appears in the column menu. E.g. the Apply button will have the same meaning when used in the tool panel. Also the relationship with the Floating Filter (if active) will be the same.
- If the filter is open on the tool panel and then the user subsequently opens the column menu, the tool panel filter will be closed. Because the filter is the same filter instance, it will only appear at one location at any given time.

## Expand / Collapse Filter Groups

It is possible to expand and collapse filter groups in the Filters Tool Panel by invoking methods on the Filters Tool Panel Instance. These methods are shown below:

```ts
interface IFiltersToolPanel {
    expandFilterGroups(groupIds?: string[]): void;
    collapseFilterGroups(groupIds?: string[]): void;
    ... // other methods
}
```

The code snippet below shows how to expand and collapse filter groups using the Filters Tool Panel instance:

```jsx
// lookup Filters Tool Panel instance by id, in this case using the default filter instance id
const filtersToolPanel = gridApi.getToolPanelInstance('filters');

// expands all filter groups in the Filters Tool Panel
filtersToolPanel.expandFilterGroups();

// collapses all filter groups in the Filters Tool Panel
filtersToolPanel.collapseFilterGroups();

// expands the 'athlete' and 'competition' filter groups in the Filters Tool Panel
filtersToolPanel.expandFilterGroups(['athleteGroupId', 'competitionGroupId']);

// collapses the 'competition' filter group in the Filters Tool Panel
filtersToolPanel.collapseFilters(['competitionGroupId']);
```

Notice in the snippet above that it's possible to target individual filter groups by supplying `groupId`s.

The example below demonstrates these methods in action. Note the following:

- When the grid is initialised, `collapseFilterGroups()` is invoked in the `onGridReady` callback to collapse all filter groups in the tool panel.
- Clicking **Expand Athlete & Competition** just expands the 'Athlete' and 'Competition' filter groups using: `expandFilterGroups(['athleteGroupId', 'competitionGroupId'])`.
- Clicking **Collapse Competition** just collapses the 'Competition' filter group using: `collapseFilterGroups(['competitionGroupId'])`.
- Clicking **Expand All** expands all filter groups using: `expandFilterGroups()`. Note that 'Sport' is not expanded as it is not a filter group.
- Clicking **Collapse All** collapses all filter groups using: `collapseFilterGroups()`.

#### Expand / Collapse Groups

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  NumberFilterModule,
  ClientSideRowModelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
  TextFilterModule,
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
    {
      groupId: "athleteGroupId",
      headerName: "Athlete",
      children: [
        {
          headerName: "Name",
          field: "athlete",
          minWidth: 200,
          filter: "agTextColumnFilter",
        },
        { field: "age" },
        {
          groupId: "competitionGroupId",
          headerName: "Competition",
          children: [{ field: "year" }, { field: "date", minWidth: 180 }],
        },
        { field: "country", minWidth: 200 },
      ],
    },
    { colId: "sport", field: "sport", minWidth: 200 },
    {
      headerName: "Medals",
      children: [
        { field: "gold" },
        { field: "silver" },
        { field: "bronze" },
        { field: "total" },
      ],
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
    };
  }, []);

  const onGridReady = useCallback((params: GridReadyEvent) => {
    // initially collapse all filter groups
    params.api.getToolPanelInstance("filters")!.collapseFilterGroups();
  }, []);
  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  const collapseAll = useCallback(() => {
    gridRef
      .current!.api.getToolPanelInstance("filters")!
      .collapseFilterGroups();
  }, []);

  const expandAthleteAndCompetition = useCallback(() => {
    gridRef
      .current!.api.getToolPanelInstance("filters")!
      .expandFilterGroups(["athleteGroupId", "competitionGroupId"]);
  }, []);

  const collapseCompetition = useCallback(() => {
    gridRef
      .current!.api.getToolPanelInstance("filters")!
      .collapseFilterGroups(["competitionGroupId"]);
  }, []);

  const expandAll = useCallback(() => {
    gridRef.current!.api.getToolPanelInstance("filters")!.expandFilterGroups();
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div>
            <span className="button-group">
              <button onClick={expandAthleteAndCompetition}>
                Expand Athlete &amp; Competition
              </button>
              <button onClick={collapseCompetition}>
                Collapse Competition
              </button>
              <button onClick={expandAll}>Expand All</button>
              <button onClick={collapseAll}>Collapse All</button>
            </span>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              sideBar={"filters"}
              onGridReady={onGridReady}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Expand / Collapse Groups](https://www.ag-grid.com/examples/tool-panel-filters/expand-collapse-groups/reactFunctionalTs)

## Expand / Collapse Filters

It is possible to expand and collapse the filters in the Filters Tool Panel by invoking methods on the Filters Tool Panel Instance. These methods are shown below:

```ts
interface IFiltersToolPanel {
    expandFilters(colIds?: string[]): void;
    collapseFilters(colIds?: string[]): void;
    ... // other methods
}
```

The code snippet below shows how to expand and collapse filters using the Filters Tool Panel instance:

```jsx
// lookup Filters Tool Panel instance by id, in this case using the default filter instance id
const filtersToolPanel = gridApi.getToolPanelInstance('filters');

// expands all filters in the Filters Tool Panel
filtersToolPanel.expandFilters();

// collapses all filters in the Filters Tool Panel
filtersToolPanel.collapseFilters();

// expands 'year' and 'sport' filters in the Filters Tool Panel
filtersToolPanel.expandFilters(['year', 'sport']);

// collapses the 'year' filter in the Filters Tool Panel
filtersToolPanel.expandFilters(['year']);
```

Notice in the snippet above that it's possible to target individual filters by supplying `colId`s.

The example below demonstrates these methods in action. Note the following:

- When the grid is initialised all filters are collapsed by default
- Clicking **Expand Year & Sport** just expands the 'year' and 'sport' filters by invoking: `expandFilters(['year', 'sport'])`.
- Clicking **Collapse Year** just collapses the 'year' filter using: `collapseFilters(['year'])`.
- Clicking **Expand All** expands all filters using: `expandFilters()`.
- Clicking **Collapse All** collapses all filters using: `collapseFilters()`.

#### Expand / Collapse Filters

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  NumberFilterModule,
  ClientSideRowModelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
  TextFilterModule,
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
    {
      groupId: "athleteGroupId",
      headerName: "Athlete",
      children: [
        {
          headerName: "Name",
          field: "athlete",
          minWidth: 200,
          filter: "agTextColumnFilter",
        },
        { field: "age" },
        {
          groupId: "competitionGroupId",
          headerName: "Competition",
          children: [{ field: "year" }, { field: "date", minWidth: 180 }],
        },
        { field: "country", minWidth: 200 },
      ],
    },
    { colId: "sport", field: "sport", minWidth: 200 },
    {
      headerName: "Medals",
      children: [
        { field: "gold" },
        { field: "silver" },
        { field: "bronze" },
        { field: "total" },
      ],
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  const collapseAll = useCallback(() => {
    gridRef.current!.api.getToolPanelInstance("filters")!.collapseFilters();
  }, []);

  const expandYearAndSport = useCallback(() => {
    gridRef
      .current!.api.getToolPanelInstance("filters")!
      .expandFilters(["year", "sport"]);
  }, []);

  const collapseYear = useCallback(() => {
    gridRef
      .current!.api.getToolPanelInstance("filters")!
      .collapseFilters(["year"]);
  }, []);

  const expandAll = useCallback(() => {
    gridRef.current!.api.getToolPanelInstance("filters")!.expandFilters();
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div>
            <span className="button-group">
              <button onClick={expandYearAndSport}>
                Expand Year &amp; Sport
              </button>
              <button onClick={collapseYear}>Collapse Year</button>
              <button onClick={expandAll}>Expand All</button>
              <button onClick={collapseAll}>Collapse All</button>
            </span>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              sideBar={"filters"}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Expand / Collapse Filters](https://www.ag-grid.com/examples/tool-panel-filters/expand-collapse-filters/reactFunctionalTs)

## Custom Filters Layout

The order of columns in the Filters Tool Panel is derived from the `columnDefs` supplied in the grid options, and is kept in sync with the grid when columns are moved by default. However custom filter layouts can also be defined by invoking the following method on the Filters Tool Panel Instance:

```ts
interface IFiltersToolPanel {
    setFilterLayout(colDefs: ColDef[]): void;
    ... // other methods
}
```

Notice that the same [Column Definitions](https://www.ag-grid.com/react-data-grid/column-definitions/) that are supplied in the grid options are also passed to `setFilterLayout(colDefs)`.

The code snippets below show how to set custom filter layouts using the Filters Tool Panel instance:

```jsx
// original column definitions supplied to the grid
const [columnDefs, setColumnDefs] = useState([
    { field: 'a' },
    { field: 'b' },
    { field: 'c' },
]);

<AgGridReact columnDefs={columnDefs} />
```

```jsx
// lookup Filters Tool Panel instance by id, in this case using the default columns instance id
const filtersToolPanel = gridApi.getToolPanelInstance('filters');

// set custom Filters Tool Panel layout
filtersToolPanel.setFilterLayout([
    {
        headerName: 'Group 1', // group doesn't appear in grid
        children: [
            { field: 'c' }, // custom column order with column "b" omitted
            { field: 'a' }
        ]
    }
]);
```

Notice from the snippet above that it's possible to define groups in the tool panel that don't exist in the grid. Also note that filters can be omitted or positioned in a different order. However note that all referenced columns (that contain filters) must already exist in the grid.

> **Note**
>
> When providing a custom layout it is recommend to enable `suppressSyncLayoutWithGrid` in the tool panel params to prevent users changing the layout when moving columns in the grid.

The example below shows two custom layouts for the Filters Tool Panel. Note the following:

- When the grid is initialised the filter layout in the Filters Tool Panel matches what is supplied to the grid in `gridOptions.columnDefs`.
- Clicking **Custom Sort Layout** invokes `setFilterLayout(colDefs)` with a list of column definitions arranged in ascending order.
- Clicking **Custom Group Layout** invokes `setFilterLayout(colDefs)` with a list of column definitions containing groups that don't appear in the grid.
- Moving columns in the grid won't affect the custom layouts as `suppressSyncLayoutWithGrid` is enabled.

#### Custom Filters Layout

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  NumberFilterModule,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  NumberFilterModule,
  ClientSideRowModelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  SetFilterModule,
  TextFilterModule,
];

const sortedToolPanelColumnDefs = [
  {
    headerName: "Athlete",
    children: [
      { field: "age" },
      { field: "country" },
      { headerName: "Name", field: "athlete" },
    ],
  },
  {
    headerName: "Competition",
    children: [{ field: "date" }, { field: "year" }],
  },
  {
    headerName: "Medals",
    children: [
      { field: "bronze" },
      { field: "gold" },
      { field: "silver" },
      { field: "total" },
    ],
  },
  { colId: "sport", field: "sport", width: 110 },
];

const customToolPanelColumnDefs = [
  {
    headerName: "Dummy Group 1",
    children: [
      { field: "age" },
      { headerName: "Name", field: "athlete" },
      {
        headerName: "Dummy Group 2",
        children: [{ colId: "sport" }, { field: "country" }],
      },
    ],
  },
  {
    headerName: "Medals",
    children: [
      { field: "total" },
      { field: "bronze" },
      {
        headerName: "Dummy Group 3",
        children: [{ field: "silver" }, { field: "gold" }],
      },
    ],
  },
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<(ColDef | ColGroupDef)[]>([
    {
      headerName: "Athlete",
      children: [
        {
          headerName: "Name",
          field: "athlete",
          minWidth: 200,
          filter: "agTextColumnFilter",
        },
        { field: "age" },
        { field: "country", minWidth: 200 },
      ],
    },
    {
      headerName: "Competition",
      children: [{ field: "year" }, { field: "date", minWidth: 180 }],
    },
    { colId: "sport", field: "sport", minWidth: 200 },
    {
      headerName: "Medals",
      children: [
        { field: "gold" },
        { field: "silver" },
        { field: "bronze" },
        { field: "total" },
      ],
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      filter: true,
    };
  }, []);
  const sideBar = useMemo<
    SideBarDef | string | string[] | boolean | null
  >(() => {
    return {
      toolPanels: [
        {
          id: "filters",
          labelDefault: "Filters",
          labelKey: "filters",
          iconKey: "filter",
          toolPanel: "agFiltersToolPanel",
          toolPanelParams: {
            suppressExpandAll: false,
            suppressFilterSearch: false,
            // prevents custom layout changing when columns are reordered in the grid
            suppressSyncLayoutWithGrid: true,
          },
        },
      ],
      defaultToolPanel: "filters",
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  const setCustomSortLayout = useCallback(() => {
    const filtersToolPanel =
      gridRef.current!.api.getToolPanelInstance("filters");
    filtersToolPanel!.setFilterLayout(sortedToolPanelColumnDefs);
  }, [sortedToolPanelColumnDefs]);

  const setCustomGroupLayout = useCallback(() => {
    const filtersToolPanel =
      gridRef.current!.api.getToolPanelInstance("filters");
    filtersToolPanel!.setFilterLayout(customToolPanelColumnDefs);
  }, [customToolPanelColumnDefs]);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div>
            <span className="button-group">
              <button onClick={setCustomSortLayout}>Custom Sort Layout</button>
              <button onClick={setCustomGroupLayout}>
                Custom Group Layout
              </button>
            </span>
          </div>

          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              sideBar={sideBar}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Custom Filters Layout](https://www.ag-grid.com/examples/tool-panel-filters/custom-layout/reactFunctionalTs)
