---
product: "AG Grid"
title: "Text Filter"
description: "Text Filters allow you to filter string data."
framework: javascript
version: "36.2.0"
related:
    - title: "Number Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-number/"
    - title: "BigInt Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-bigint/"
    - title: "Date Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-date/"
    - title: "Set Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-set/"
    - title: "Multi Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-multi/"
    - title: "Filter Conditions"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-conditions/"
    - title: "Applying Filters"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-applying/"
    - title: "Filter API"
      url: "https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-api/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Text Filter

Text Filters allow you to filter string data.

![Text Filter](https://www.ag-grid.com/archive/36.2.0/_astro/text-filter.m8-Z5BzG.png)

## Enabling Text Filters

#### Text Filter

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, TextFilterModule]);

const columnDefs: ColDef[] = [
  {
    field: "athlete",
    filter: true,
  },
  {
    field: "country",
    filter: "agTextColumnFilter",
  },
  {
    field: "sport",
    filter: true,
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    flex: 1,
  },
  columnDefs,
  rowData: null,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Text Filter](https://www.ag-grid.com/archive/36.2.0/examples/filter-text/text-filter/typescript/)

The Text Filter is the default filter used in AG Grid Community, but it can also be explicitly configured as shown below:

```js
const gridOptions = {
    columnDefs: [
        {
            field: 'athlete',
            // Text Filter is used by default in Community version
            filter: true,
            filterParams: {
                // pass in additional parameters to the Text Filter
            },
        },
        {
            field: 'country',
            // explicitly configure column to use the Text Filter
            filter: 'agTextColumnFilter',
            filterParams: {
                // pass in additional parameters to the Text Filter
            },
        },
    ],

    // other grid options ...
}
```

## Text Filter Parameters

Text Filters are configured though the `filterParams` attribute of the column definition (`ITextFilterParams` interface):

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `browserAutoComplete` | `boolean \| string` |  |  |  |
| `buttons` | `FilterAction[]` |  |  |  |
| `caseSensitive` | `boolean` |  |  |  |
| `closeOnApply` | `boolean` |  |  |  |
| `debounceMs` | `number` |  |  |  |
| `defaultJoinOperator` | `JoinOperator` |  |  |  |
| `defaultOption` | `TextFilterOptionKey \| CustomFilterOptionKey` |  |  |  |
| `filterOptions` | `(IFilterOptionDef \| TextFilterOptionKey \| AdvancedFilterOnlyOptionKey)[]` |  |  |  |
| `filterPlaceholder` | `FilterPlaceholderFunction \| string` |  |  |  |
| `maxNumConditions` | `number` |  |  |  |
| `numAlwaysVisibleConditions` | `number` |  |  |  |
| `readOnly` | `boolean` |  |  |  |
| `textFormatter` | `Function` |  |  |  |
| `textMatcher` | `TextMatcher` |  |  |  |
| `trimInput` | `boolean` |  |  |  |

The following example demonstrates configuring different Text Filter parameters:

- For the **Athlete** column:
  - The filter has a debounce of 200ms (`debounceMs = 200`).
  - Only one Filter Condition is allowed (`maxNumConditions = 1`)
- For the **Country** column:
  - The filter input will be trimmed when the filter is applied (`trimInput = true`)
  - There is a debounce of 1000ms (`debounceMs = 1000`)
- For the **Sport** column:
  - The filter is case-sensitive (`caseSensitive = true`)

#### Text Filter Parameters

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ITextFilterParams,
  ModuleRegistry,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, TextFilterModule]);

const columnDefs: ColDef[] = [
  {
    field: "athlete",
    filterParams: {
      debounceMs: 200,
      maxNumConditions: 1,
    } as ITextFilterParams,
  },
  {
    field: "country",
    filterParams: {
      trimInput: true,
      debounceMs: 1000,
    } as ITextFilterParams,
  },
  {
    field: "sport",
    filterParams: {
      caseSensitive: true,
    } as ITextFilterParams,
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    flex: 1,
    filter: true,
  },
  columnDefs,
  rowData: null,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Text Filter Parameters](https://www.ag-grid.com/archive/36.2.0/examples/filter-text/text-filter-parameters/typescript/)

Filter input fields share the grid-wide input behaviour (clear button, browser autocomplete) described in [Input Fields](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/input-fields/).

## Text Formatter

By default, the grid compares the Text Filter with the values in a case-insensitive way, by converting both the filter text and the values to lower case and comparing them; for example, `'o'` will match `'Olivia'` and `'Salmon'`. If you instead want to have case-sensitive matches, you can set `caseSensitive = true` in the `filterParams`, so that no lowercasing is performed. In this case, `'o'` would no longer match `'Olivia'`.

You might have more advanced requirements, for example to ignore accented characters. In this case, you can provide your own `textFormatter`, which is a function with the following signature:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `textFormatter` | `Function` |  |  |  |

`from` is the value coming from the grid. This can be from the `valueGetter` if there is any for the column, or the value as originally provided in the `rowData`. The function should return a string to be used for the purpose of filtering.

The Text Formatter is applied to both the filter text and the values before they are compared.

The following is an example function to remove accents and convert to lower case.

```js
const toLowerWithoutAccents = value => value == null
    ? null
    : value.toLowerCase()
        .replace(/[àáâãäå]/g, 'a')
        .replace(/æ/g, 'ae')
        .replace(/ç/g, 'c')
        .replace(/[èéêë]/g, 'e')
        .replace(/[ìíîï]/g, 'i')
        .replace(/ñ/g, 'n')
        .replace(/[òóôõö]/g, 'o')
        .replace(/œ/g, 'oe')
        .replace(/[ùúûü]/g, 'u')
        .replace(/[ýÿ]/g, 'y');
```

Note that when providing a Text Formatter, the `caseSensitive` parameter is ignored. In this situation, if you want to do a case-insensitive comparison, you will need to perform case conversion inside the `textFormatter` function.

The example below demonstrates a `textFormatter` on the **Athlete** column:

- If you search for `'o'` it will find `'ö'`. You can try this by searching the string `'Bjo'`.

#### Text Formatter

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ITextFilterParams,
  ModuleRegistry,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, TextFilterModule]);

const athleteFilterParams: ITextFilterParams = {
  textFormatter: (r) => {
    if (r == null) return null;

    return r
      .toLowerCase()
      .replace(/[àáâãäå]/g, "a")
      .replace(/æ/g, "ae")
      .replace(/ç/g, "c")
      .replace(/[èéêë]/g, "e")
      .replace(/[ìíîï]/g, "i")
      .replace(/ñ/g, "n")
      .replace(/[òóôõö]/g, "o")
      .replace(/œ/g, "oe")
      .replace(/[ùúûü]/g, "u")
      .replace(/[ýÿ]/g, "y");
  },
};

const columnDefs: ColDef[] = [
  {
    field: "athlete",
    filterParams: athleteFilterParams,
  },
  {
    field: "country",
  },
  {
    field: "sport",
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    flex: 1,
    filter: true,
  },
  columnDefs,
  rowData: null,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Text Formatter](https://www.ag-grid.com/archive/36.2.0/examples/filter-text/text-formatter/typescript/)

## Text Custom Matcher

In most cases, you can customise the Text Filter matching logic by providing your own [Text Formatter](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-text/#text-formatter), e.g. to remove or replace characters in the filter text and values. The Text Formatter is applied to both the filter text and values before the filter comparison is performed.

For more advanced use cases, you can provide your own `textMatcher` to decide when to include a row in the filtered results. For example, you might want to apply different logic for the filter option `equals` than for `contains`.

The [Advanced Filter](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-advanced/) compares text with the same `textFormatter`, `textMatcher` and `trimInput` the column is configured with, so a condition written there matches the rows this filter matches. `params.source` tells a `textFormatter` or `textMatcher` which of the two is asking.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `textMatcher` | `TextMatcher` |  |  |  |

The following is an example of a `textMatcher` that mimics the current implementation of AG Grid. This can be used as a template to create your own.

```js
const gridOptions = {
    columnDefs: [
        {
            field: 'athlete',
            filter: 'agTextColumnFilter',
            filterParams: {
                textMatcher: ({ filterOption, value, filterText }) => {
                    if (filterText == null) {
                        return false;
                    }
                    switch (filterOption) {
                        case 'contains':
                            return value.indexOf(filterText) >= 0;
                        case 'notContains':
                            return value.indexOf(filterText) < 0;
                        case 'equals':
                            return value === filterText;
                        case 'notEqual':
                            return value != filterText;
                        case 'startsWith':
                            return value.indexOf(filterText) === 0;
                        case 'endsWith':
                            const index = value.lastIndexOf(filterText);
                            return index >= 0 && index === (value.length - filterText.length);
                        default:
                            // should never happen
                            console.warn('invalid filter type ' + filterOption);
                            return false;
                    }
                }
            }
        }
    ],

    // other grid options ...
}
```

Note that the `textMatcher` is not called for the `blank` and `notBlank` options.

The example below demonstrates a `textMatcher` on the **Country** column:

- Most options are implemented as per the default grid implementation above.
- The `contains` option has additional logic so that aliases can be entered in the filter. E.g. if you filter using the text `'usa'` it will match `United States`, or `'holland'` will match `'Netherlands'`.

#### Text Custom Matcher

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ITextFilterParams,
  ModuleRegistry,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, TextFilterModule]);

function contains(target: string, lookingFor: string) {
  return target && target.indexOf(lookingFor) >= 0;
}

const countryFilterParams: ITextFilterParams = {
  textMatcher: ({ filterOption, value, filterText }) => {
    if (filterText == null) {
      return false;
    }
    switch (filterOption) {
      case "contains":
        const aliases: Record<string, string> = {
          usa: "united states",
          holland: "netherlands",
        };

        const literalMatch = contains(value, filterText || "");

        return !!literalMatch || !!contains(value, aliases[filterText || ""]);
      case "notContains":
        return value.indexOf(filterText) < 0;
      case "equals":
        return value === filterText;
      case "notEqual":
        return value != filterText;
      case "startsWith":
        return value.indexOf(filterText) === 0;
      case "endsWith":
        const index = value.lastIndexOf(filterText);
        return index >= 0 && index === value.length - filterText.length;
      default:
        // should never happen
        console.warn("invalid filter type " + filterOption);
        return false;
    }
  },
};

const columnDefs: ColDef[] = [
  {
    field: "country",
    filterParams: countryFilterParams,
  },
  {
    field: "athlete",
  },
  {
    field: "sport",
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    flex: 1,
    filter: true,
  },
  columnDefs: columnDefs,
  rowData: null,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Text Custom Matcher](https://www.ag-grid.com/archive/36.2.0/examples/filter-text/text-custom-matcher/typescript/)

## Text Filter Model

The Filter Model describes the current state of the applied Text Filter. If only one [Filter Condition](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-conditions/) is set, this will be a `TextFilterModel`:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | `TextFilterOptionKey \| CustomFilterOptionKey \| null` |  |  |  |
| `filterType` | `'text'` |  |  |  |
| `filter` | `string \| null` |  |  |  |
| `filterTo` | `string \| null` |  |  |  |

If more than one Filter Condition is set, then multiple instances of the model are created and wrapped inside a Combined Model (`ICombinedSimpleModel<TextFilterModel>`). A Combined Model looks as follows:

```ts
// A filter combining multiple conditions
interface ICombinedSimpleModel<TextFilterModel> {
    filterType: string;

    operator: JoinOperator;

    // multiple instances of the Filter Model
    conditions: TextFilterModel[];
}

type JoinOperator = 'AND' | 'OR';
```

An example of a Filter Model with two conditions is as follows:

```js
// Text Filter with two conditions, both are equals type
const textEqualsSwimmingOrEqualsGymnastics = {
    filterType: 'text',
    operator: 'OR',
    conditions: [
        {
            filterType: 'text',
            type: 'equals',
            filter: 'Swimming'
        },
        {
            filterType: 'text',
            type: 'equals',
            filter: 'Gymnastics'
        }
    ]
};
```

## Text Filter Options

The Text Filter presents a list of [Filter Options](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-conditions/#filter-options) to the user.

The list of options is as follows:

| Option Name | Option Key | Included by Default |
| --- | --- | --- |
| Contains | `contains` | Yes |
| Does not contain | `notContains` | Yes |
| Equals | `equals` | Yes |
| Does not equal | `notEqual` | Yes |
| Begins with | `startsWith` | Yes |
| Ends with | `endsWith` | Yes |
| Blank | `blank` | Yes |
| Not blank | `notBlank` | Yes |
| Choose one | `empty` | No |

Note that the `empty` filter option is primarily used when creating [Custom Filter Options](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-conditions/#custom-filter-options). When 'Choose one' is displayed, the filter is not active.

The default option for the Text Filter is `contains`.

When providing filter options, the default filter option (or the first option if no default set) must be an option that displays an input or the `empty` filter option (as a filter option with no inputs would mean the filter is active by default).

The example below demonstrates configuring different filter options:

- For the **Athlete** column, there are only two filter options: `filterOptions = ['contains', 'notContains']`.
- For the **Country** column, there is only one filter option: `filterOptions = ['contains']`.
- For the **Sport** column, there is a different default filter option: `defaultOption = 'startsWith'`.

#### Text Filter Options

```ts
import {
  ClientSideRowModelModule,
  ColDef,
  GridApi,
  GridOptions,
  ITextFilterParams,
  ModuleRegistry,
  TextFilterModule,
  createGrid,
  enableDevValidations,
} from "ag-grid-community";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([ClientSideRowModelModule, TextFilterModule]);

const columnDefs: ColDef[] = [
  {
    field: "athlete",
    filterParams: {
      filterOptions: ["contains", "notContains"],
      maxNumConditions: 1,
    } as ITextFilterParams,
  },
  {
    field: "country",
    filterParams: {
      filterOptions: ["contains"],
    } as ITextFilterParams,
  },
  {
    field: "sport",
    filterParams: {
      defaultOption: "startsWith",
    } as ITextFilterParams,
  },
];

let gridApi: GridApi<IOlympicData>;

const gridOptions: GridOptions<IOlympicData> = {
  defaultColDef: {
    flex: 1,
    filter: true,
  },
  columnDefs,
  rowData: null,
};

const gridDiv = document.querySelector<HTMLElement>("#myGrid")!;
gridApi = createGrid(gridDiv, gridOptions);

fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
  .then((response) => response.json())
  .then((data: IOlympicData[]) => gridApi!.setGridOption("rowData", data));
```

[Live example: Text Filter Options](https://www.ag-grid.com/archive/36.2.0/examples/filter-text/text-filter-options/typescript/)

## Text Filter Values

By default, the values supplied to the Text Filter are retrieved from the data based on the `field` attribute. This can be overridden by providing a `filterValueGetter` in the Column Definition. This is similar to using a [Value Getter](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/value-getters/), but is specific to the filter.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `filterValueGetter` | `string \| ValueGetterFunc` |  |  |  |

## Applying the Text Filter

Applying the Text Filter is described in more detail in the following sections:

- [Apply, Clear, Reset and Cancel Buttons](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-applying/#apply-clear-reset-and-cancel-buttons)
- [Applying the UI Model](https://www.ag-grid.com/archive/36.2.0/javascript-data-grid/filter-applying/#applying-the-ui-model)

## Data Updates

The Text Filter is not affected by data changes. When the grid data is updated, the filter value will remain unchanged and the filter will be re-applied based on the updated data (e.g. the displayed rows will update if necessary).
