---
title: "Floating Filter Component - Legacy"
framework: react
version: "36.1.0"
---

# Floating Filter Component - Legacy

> **Warning**
>
> This page describes the old way of declaring custom floating filter components when the grid option `enableFilterHandlers` is not set. It is strongly recommended to instead use the new behaviour described on the [Floating Filter Component](https://www.ag-grid.com/react-data-grid/component-floating-filter/) page.

Floating Filter Components allow you to add your own floating filter types to AG Grid. You can create a Custom Floating Filter Component to work alongside one of the grid's Provided Filters, or alongside a Custom Filter.

## Example: Custom Floating Filter

In the following example you can see how the Gold, Silver, Bronze and Total columns have a custom floating filter `NumberFloatingFilter`. This filter substitutes the standard floating filter for an input box that the user can change to adjust how many medals of each column to filter by based on a greater than filter.

#### Custom Floating Filter

```tsx
'use client';
import { useFetchJson } from './useFetchJson';
import React, { StrictMode, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type { ColDef } from "ag-grid-community";
import {
  ClientSideRowModelModule,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import type { IOlympicData } from "./interfaces";
import NumberFloatingFilterComponent from "./numberFloatingFilterComponent";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
];

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

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", filter: false },
    {
      field: "gold",
      filter: "agNumberColumnFilter",
      suppressHeaderFilterButton: true,
      floatingFilterComponent: NumberFloatingFilterComponent,
      floatingFilterComponentParams: {
        color: "gold",
      },
      suppressFloatingFilterButton: true,
    },
    {
      field: "silver",
      filter: "agNumberColumnFilter",
      suppressHeaderFilterButton: true,
      floatingFilterComponent: NumberFloatingFilterComponent,
      floatingFilterComponentParams: {
        color: "silver",
      },
      suppressFloatingFilterButton: true,
    },
    {
      field: "bronze",
      filter: "agNumberColumnFilter",
      suppressHeaderFilterButton: true,
      floatingFilterComponent: NumberFloatingFilterComponent,
      floatingFilterComponentParams: {
        color: "#CD7F32",
      },
      suppressFloatingFilterButton: true,
    },
    {
      field: "total",
      filter: "agNumberColumnFilter",
      suppressHeaderFilterButton: true,
      floatingFilterComponent: NumberFloatingFilterComponent,
      floatingFilterComponentParams: {
        color: "unset",
      },
      suppressFloatingFilterButton: true,
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
      floatingFilter: 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}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Custom Floating Filter](https://www.ag-grid.com/examples/component-floating-filter-legacy/custom-floating-filter/reactFunctionalTs)

## Implementing a Floating Filter Component

Custom floating filter components are controlled components, which receive a filter model as part of the props, and pass model updates back to the grid via the `onModelChange` callback. A filter model of `null` means that no filter is applied (the filter displays as inactive). Note that the filter is applied immediately when `onModelChange` is called.

```jsx
export default ({ model, onModelChange }) => {
    return (
        <div>
            <input
                type="text"
                value={model || ''}
                onChange={({ target: { value }}) => onModelChange(value === '' ? null : value)}
            />
        </div>
    );
}
```

> **Note**
>
> In previous versions of the grid, custom components were declared in an imperative way. See [Migrating to Use reactiveCustomComponents](https://www.ag-grid.com/react-data-grid/upgrading-to-ag-grid-31-1/#migrating-custom-components-to-use-reactivecustomcomponents-option) for details on how to migrate to the current format.

## Custom Floating Filter Parameters

### Floating Filter Props

The following props are passed to the custom floating filter components (`CustomFloatingFilterProps` interface). If custom props are provided via the `colDef.floatingFilterParams` property, these will be additionally added to the props object, overriding items of the same name if a name clash exists.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `model` | `TModel \| null` |  |  | The current filter model for the component. |
| `onModelChange` | `Function` |  |  | Callback that should be called every time the model in the component changes. |
| `filterParams` | `IFilterParams` |  |  | The params object passed to the filter. This is to allow the floating filter access to the configuration of the parent filter. For example, the provided filters use debounceMs from the parent filter params. |
| `filterPlaceholder` | `string \| boolean` |  |  | Placeholder text for the filter textbox. When set to `true`, inherits the placeholder text of the parent filter. |
| `currentParentModel` | `Function` |  |  | This is a shortcut to invoke getModel on the parent filter. If the parent filter doesn't exist (filters are lazily created as needed) then it returns null rather than calling getModel() on the parent filter. |
| `parentFilterInstance` | `Function` |  |  | Gets a reference to the parent filter. The result is returned asynchronously via a callback as the parent filter may not exist yet. If it does not exist, it is created and asynchronously returned (AG Grid itself does not create components asynchronously, however if providing a framework provided filter e.g. React, it might be). The floating filter can then call any method it likes on the parent filter. The parent filter will typically provide its own method for the floating filter to call to set the filter. For example, if creating custom filter A, it should have a method your floating A can call to set the state when the user updates via the floating filter. |
| `column` | [`Column`](https://www.ag-grid.com/react-data-grid/column-object/) |  |  | The column this filter is for. |
| `showParentFilter` | `Function` |  |  | Shows the parent filter popup. |
| `api` | [`GridApi`](https://www.ag-grid.com/react-data-grid/grid-api/) |  |  | The grid api. |
| `context` | [`TContext`](https://www.ag-grid.com/react-data-grid/typescript-generics/#context-tcontext) |  |  | Application context as set on `gridOptions.context`. |

### Floating Filter Callbacks

The following callbacks can be passed to the `useGridFloatingFilter` hook (`CustomFloatingFilterCallbacks` interface). All the callbacks are optional, and the hook only needs to be used if callbacks are provided.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `afterGuiAttached` | `Function` |  |  | Optional: A hook to perform any necessary operation just after the GUI for this component has been rendered on the screen. This is useful for any logic that requires attachment before executing, such as putting focus on a particular DOM element. |

## Floating Filter Lifecycle

Floating filters do not contain filter logic themselves, they are just an additional UI component for the underlying filter component. For this reason, the floating filters lifecycle is bound to the visibility of the column; if you hide a column (either set not visible, or horizontally scroll the column out of view) then the floating filter UI component is destroyed. If the column comes back into view, it is created again. This is different to column filters, where the column filter will exist as long as the column exists, regardless of the column's visibility.

To see examples of the different ways to implement floating filters please refer to the examples below.

## Example: Custom Filter And Custom Floating Filter

This example extends the previous example by also providing its own custom filter `NumberFilter` in the Gold, Silver, Bronze and Total columns.

#### Custom Filter and Floating Filter

```tsx
'use client';
import { useFetchJson } from './useFetchJson';
import React, { StrictMode, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type { ColDef } from "ag-grid-community";
import {
  ClientSideRowModelModule,
  CustomFilterModule,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import type { IOlympicData } from "./interfaces";
import NumberFilterComponent from "./numberFilterComponent";
import NumberFloatingFilterComponent from "./numberFloatingFilterComponent";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  CustomFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
];

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

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", filter: "agTextColumnFilter" },
    {
      field: "gold",
      floatingFilterComponent: NumberFloatingFilterComponent,
      filter: NumberFilterComponent,
      suppressFloatingFilterButton: true,
    },
    {
      field: "silver",
      floatingFilterComponent: NumberFloatingFilterComponent,
      filter: NumberFilterComponent,
      suppressFloatingFilterButton: true,
    },
    {
      field: "bronze",
      floatingFilterComponent: NumberFloatingFilterComponent,
      filter: NumberFilterComponent,
      suppressFloatingFilterButton: true,
    },
    {
      field: "total",
      floatingFilterComponent: NumberFloatingFilterComponent,
      filter: NumberFilterComponent,
      suppressFloatingFilterButton: true,
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
      floatingFilter: 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}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Custom Filter and Floating Filter](https://www.ag-grid.com/examples/component-floating-filter-legacy/custom-filter-and-floating-filter/reactFunctionalTs)

## Example: Custom Filter And Read-Only Floating Filter

If you want to provide a custom filter but don't want to provide an equivalent custom floating filter, you can implement `getModelAsString()` and you will get a read-only floating filter for free.

This example uses the previous custom filter but implements `getModelAsString()`. Note how there are no custom floating filters and yet each column using `NumberFilter` (Gold, Silver, Bronze and Total) has a read-only floating filter that gets updated as you change the values from the main filter.

#### Custom Filter Only

```tsx
'use client';
import { useFetchJson } from './useFetchJson';
import React, { StrictMode, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type { ColDef } from "ag-grid-community";
import {
  ClientSideRowModelModule,
  CustomFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import type { IOlympicData } from "./interfaces";
import NumberFilterComponent from "./numberFilterComponent";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [CustomFilterModule, ClientSideRowModelModule];

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

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", width: 150, filter: false },
    {
      field: "gold",
      width: 100,
      filter: NumberFilterComponent,
      suppressHeaderMenuButton: true,
    },
    {
      field: "silver",
      width: 100,
      filter: NumberFilterComponent,
      suppressHeaderMenuButton: true,
    },
    {
      field: "bronze",
      width: 100,
      filter: NumberFilterComponent,
      suppressHeaderMenuButton: true,
    },
    {
      field: "total",
      width: 100,
      filter: NumberFilterComponent,
      suppressHeaderMenuButton: true,
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
      floatingFilter: 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}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Custom Filter Only](https://www.ag-grid.com/examples/component-floating-filter-legacy/custom-filter/reactFunctionalTs)

## Sliding Floating Filters

The below example shows how to create a custom floating filter re-using the out-of-the-box Number Filter .

#### Sliding Floating Filter Component

```tsx
'use client';
import { useFetchJson } from './useFetchJson';
import React, { StrictMode, useMemo, useState } from "react";
import { createRoot } from "react-dom/client";

import type { ColDef, INumberFilterParams } from "ag-grid-community";
import {
  ClientSideRowModelModule,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import SliderFloatingFilter from "./sliderFloatingFilter";

// Enable extended validations only for development
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  TextFilterModule,
  NumberFilterModule,
  ClientSideRowModelModule,
];

const filterParams: INumberFilterParams = {
  filterOptions: ["greaterThan"],
  maxNumConditions: 1,
};

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

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "athlete", filter: false },
    {
      field: "gold",
      filter: "agNumberColumnFilter",
      filterParams: filterParams,
      floatingFilterComponent: SliderFloatingFilter,
      floatingFilterComponentParams: {
        maxValue: 7,
      },
      suppressFloatingFilterButton: true,
      suppressHeaderMenuButton: false,
    },
    {
      field: "silver",
      filter: "agNumberColumnFilter",
      filterParams: filterParams,
      floatingFilterComponent: SliderFloatingFilter,
      floatingFilterComponentParams: {
        maxValue: 5,
      },
      suppressFloatingFilterButton: true,
      suppressHeaderMenuButton: false,
    },
    {
      field: "bronze",
      filter: "agNumberColumnFilter",
      filterParams: filterParams,
      floatingFilterComponent: SliderFloatingFilter,
      floatingFilterComponentParams: {
        maxValue: 10,
      },
      suppressFloatingFilterButton: true,
      suppressHeaderMenuButton: false,
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
      filter: true,
      floatingFilter: 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={{ height: "100%", boxSizing: "border-box" }}>
          <div style={gridStyle}>
            <AgGridReact
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              alwaysShowVerticalScroll
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

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

[Live example: Sliding Floating Filter Component](https://www.ag-grid.com/examples/component-floating-filter-legacy/floating-filter-component/reactFunctionalTs)
