---
product: "AG Grid"
title: "Filter Component - Legacy"
description: "The example below shows two custom filters. The first is on the Athlete column and demonstrates a filter with \"fuzzy\" matching and the second is on the Year column with preset options."
framework: react
version: "36.2.0"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Filter Component - Legacy

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

The example below shows two custom filters. The first is on the `Athlete` column and demonstrates a filter with "fuzzy" matching and the second is on the `Year` column with preset options.

#### Custom Filter Component

```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 "./style.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CustomFilterModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import PersonFilter from "./personFilter.tsx";
import YearFilter from "./yearFilter.tsx";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  // Enable extended validations only for development
  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", minWidth: 150, filter: PersonFilter },
    { field: "year", minWidth: 130, filter: YearFilter },
    { field: "country", minWidth: 150 },
    { field: "sport" },
    { field: "gold" },
    { field: "silver" },
    { field: "bronze" },
    { field: "total" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
    };
  }, []);

  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 Component](https://www.ag-grid.com/archive/36.2.0/examples/component-filter-legacy/custom-filter-legacy/reactFunctionalTs/)

## Implementing a Filter Component

Custom 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.

To implement the filtering logic, a custom filter needs to implement the `doesFilterPass` callback, and provide it to the `useGridFilter` hook.

```jsx
export default ({ model, onModelChange, getValue }) => {
    const doesFilterPass = useCallback(({ node }) => {
        // filtering logic
        return getValue(node).contains(model);
    }, [model]);

    // register filter callbacks with the grid
    useGridFilter({ doesFilterPass });

    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/archive/36.2.0/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 Filter Parameters

### Filter Props

The following props are passed to the custom filter components (`CustomFilterProps` interface). If custom props are provided via the `colDef.filterParams` 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` |  |  |  |
| `onModelChange` | `Function` |  |  |  |
| `onUiChange` | `Function` |  |  |  |
| `column` | `Column` |  |  |  |
| `colDef` | `ColDef` |  |  |  |
| `getValue` | `Function` |  |  |  |
| `doesRowPassOtherFilter` | `Function` |  |  |  |
| `api` | `GridApi` |  |  |  |
| `context` | `TContext` |  |  |  |

### Filter Callbacks

The following callbacks can be passed to the `useGridFilter` hook (`CustomFilterCallbacks` interface). The hook must be used for filters to work. The `doesFilterPass` callback is mandatory, but all others are optional.

Note that `doesFilterPass` is only called with the [Client-Side Row Model](https://www.ag-grid.com/archive/36.2.0/react-data-grid/row-models/). If being used exclusively with other row models, it can just return `true` as the filtering logic is performed on the server.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `doesFilterPass` | `Function` |  |  |  |
| `afterGuiAttached` | `Function` |  |  |  |
| `afterGuiDetached` | `Function` |  |  |  |
| `onNewRowsLoaded` | `Function` |  |  |  |
| `onAnyFilterChanged` | `Function` |  |  |  |
| `getModelAsString` | `Function` |  |  |  |
