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

# Number Filter

Number Filters allow you to filter numeric data.

![Number Filter](https://www.ag-grid.com/archive/36.2.0/_astro/number-filter.CzQ3JNC5.png)

## Enabling Number Filters

#### Number Filter

```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,
  enableDevValidations,
} from "ag-grid-community";
import { getData } from "./data";

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

const modules = [ClientSideRowModelModule, NumberFilterModule];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
      field: "price",
      filter: true,
    },
    {
      field: "quantity",
      filter: "agNumberColumnFilter",
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 150,
    };
  }, []);

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

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

[Live example: Number Filter](https://www.ag-grid.com/archive/36.2.0/examples/filter-number/number-filter/reactFunctionalTs/)

The Number Filter is the default filter used in AG Grid Community for columns with number [Cell Data Type](https://www.ag-grid.com/archive/36.2.0/react-data-grid/cell-data-types/), but it can also be explicitly configured as shown below:

```jsx
const [columnDefs, setColumnDefs] = useState([
    {
        field: 'price',
        // Number Filter is used by default in Community version for numeric columns
        filter: true,
        filterParams: {
            // pass in additional parameters to the Number Filter
        },
    },
    {
        field: 'quantity',
        // explicitly configure column to use the Number Filter
        filter: 'agNumberColumnFilter',
        filterParams: {
            // pass in additional parameters to the Number Filter
        },
    },
]);

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

## Number Filter Parameters

Number Filters are configured through the `filterParams` attribute of the column definition (`INumberFilterParams` interface):

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `allowedCharPattern` | `string` |  |  |  |
| `browserAutoComplete` | `boolean \| string` |  |  |  |
| `buttons` | `FilterAction[]` |  |  |  |
| `closeOnApply` | `boolean` |  |  |  |
| `debounceMs` | `number` |  |  |  |
| `defaultJoinOperator` | `JoinOperator` |  |  |  |
| `defaultOption` | `ScalarFilterOptionKey \| CustomFilterOptionKey` |  |  |  |
| `filterInputType` | `'text' \| 'number'` |  |  |  |
| `filterOptions` | `(IFilterOptionDef \| ScalarFilterOptionKey \| AdvancedFilterOnlyOptionKey)[]` |  |  |  |
| `filterPlaceholder` | `FilterPlaceholderFunction \| string` |  |  |  |
| `inRangeInclusive` | `boolean` |  |  |  |
| `includeBlanksInEquals` | `boolean` |  |  |  |
| `includeBlanksInGreaterThan` | `boolean` |  |  |  |
| `includeBlanksInLessThan` | `boolean` |  |  |  |
| `includeBlanksInNotEqual` | `boolean` |  |  |  |
| `includeBlanksInRange` | `boolean` |  |  |  |
| `maxNumConditions` | `number` |  |  |  |
| `numAlwaysVisibleConditions` | `number` |  |  |  |
| `numberFormatter` | `Function` |  |  |  |
| `numberParser` | `Function` |  |  |  |
| `readOnly` | `boolean` |  |  |  |

## Custom Number Support

The default behaviour of the Number Filter is to use a `number` input, however this has mixed browser support and behaviour. If you want to override the default behaviour, or allow users to type other characters (e.g. currency symbols, commas for thousands, etc.), the Number Filter allows you to control what characters the user is allowed to type. In this case, a `text` input is used with JavaScript controlling what characters the user is allowed (rather than the browser). You can also provide custom logic to parse the provided value into a number to be used in the filtering.

Custom number support is enabled by specifying configuration similar to the following:

```jsx
const [columnDefs, setColumnDefs] = useState([
    {
        field: 'age',
        filter: 'agNumberColumnFilter',
        filterParams: {
            // note: ensure you escape as if you were creating a RegExp from a string
            allowedCharPattern: '\\d\\-\\,',
            numberParser: text => {
                return text == null ? null : parseFloat(text.replace(',', '.'));
            },
            numberFormatter: value => {
                return value == null ? null : value.toString().replace('.', ',');
            },
        }
    }
]);

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

The `allowedCharPattern` is a regex of all the characters that are allowed to be typed. A value starting `[` and ending `]` is used as written and must therefore match exactly one character; anything else is surrounded by square brackets `[]` for you. It is compared against each character an edit brings in, and an edit bringing in a character it does not admit is refused whole. That covers a paste and a drop as well as a keystroke. Text committed by an IME or another composing keyboard is not held to it, since a composition cannot be cancelled. A pattern that does not compile to a character pattern is reported as a warning and ignored.

The `numberParser` should take the user-entered text and return either a number if one can be interpreted, or `null` if not.

The `numberFormatter` should take a number (e.g. from the Filter Model) and convert it into the formatted text to be displayed, or `null` if no value.

`numberParser` and `numberFormatter` are also passed the grid `api` and `context` as a second argument, along with the `column` and `colDef` they are working on. One callback set on `defaultColDef.filterParams` can therefore serve every column it applies to. The [Advanced Filter](https://www.ag-grid.com/archive/36.2.0/react-data-grid/filter-advanced/) runs the same callbacks to read and write its operands; `params.source` is `'advancedFilter'` there and `'columnFilter'` here.

An `allowedCharPattern` of `\\d\\-\\.` will give similar behaviour to the default `number` input.

A `text` input is used when `allowedCharPattern` or `numberFormatter` is provided, unless `filterInputType` says otherwise, as a `number` input keeps only its own number syntax and would discard formatted text.

Set `filterInputType` to choose the input yourself. A `numberFormatter` writing text a `number` input can hold, such as `(value) => (value == null ? null : value.toFixed(2))`, can keep that input with `filterInputType: 'number'`. An `allowedCharPattern` applies to either input, narrowing what a `number` input already accepts.

Provide a `numberParser` alongside a `numberFormatter` to have the format read back. Without one, typed text is read with `parseFloat`, so `1,234` becomes `1`.

Pair both to have the [Advanced Filter](https://www.ag-grid.com/archive/36.2.0/react-data-grid/filter-advanced/) read and display this column's operands in the same format. With only one of them, its operands stay plain numbers.

The following example demonstrates custom number support:

- The first column shows the default Number Filter behaviour.
- The second column demonstrates custom number support, and uses commas for decimals and allows a dollar sign ($) to be included.
- Floating filters are enabled and also react to the configuration of `allowedCharPattern` and `numberFormatter`.

#### Custom Number Support

```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,
  INumberFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import { getData } from "./data";

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

const modules = [ClientSideRowModelModule, NumberFilterModule];

const numberValueFormatter = function (params: ValueFormatterParams) {
  return params.value.toFixed(2);
};

const saleFilterParams: INumberFilterParams = {
  allowedCharPattern: "\\d\\-\\,\\$",
  numberParser: (text: string | null) => {
    return text == null
      ? null
      : parseFloat(text.replace(",", ".").replace("$", ""));
  },
  numberFormatter: (value: number | null) => {
    return value == null ? null : value.toString().replace(".", ",");
  },
};

const saleValueFormatter = function (params: ValueFormatterParams) {
  const formatted = params.value.toFixed(2).replace(".", ",");
  if (formatted.indexOf("-") === 0) {
    return "-$" + formatted.slice(1);
  }
  return "$" + formatted;
};

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
      field: "sale",
      headerName: "Sale ($)",
      floatingFilter: true,
      valueFormatter: numberValueFormatter,
    },
    {
      field: "sale",
      headerName: "Sale",
      floatingFilter: true,
      filterParams: saleFilterParams,
      valueFormatter: saleValueFormatter,
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 150,
      filter: true,
    };
  }, []);

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

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

[Live example: Custom Number Support](https://www.ag-grid.com/archive/36.2.0/examples/filter-number/custom-number-support/reactFunctionalTs/)

## Number Filter Model

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

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | `ScalarFilterOptionKey \| CustomFilterOptionKey \| null` |  |  |  |
| `filterType` | `'number'` |  |  |  |
| `filter` | `number \| null` |  |  |  |
| `filterTo` | `number \| null` |  |  |  |

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

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

    operator: JoinOperator;

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

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

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

```js
// Number Filter with two conditions, both are equals type
const numberEquals18OrEquals20 = {
    filterType: 'number',
    operator: 'OR',
    conditions: [
        {
            filterType: 'number',
            type: 'equals',
            filter: 18
        },
        {
            filterType: 'number',
            type: 'equals',
            filter: 20
        }
    ]
};
```

## Number Filter Options

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

The list of options is as follows:

| Option Name | Option Key | Included by Default |
| --- | --- | --- |
| Equals | `equals` | Yes |
| Does not equal | `notEqual` | Yes |
| Greater than | `greaterThan` | Yes |
| Greater than or equal to | `greaterThanOrEqual` | Yes |
| Less than | `lessThan` | Yes |
| Less than or equal to | `lessThanOrEqual` | Yes |
| Between | `inRange` | 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/react-data-grid/filter-conditions/#custom-filter-options). When 'Choose one' is displayed, the filter is not active.

The default option for the Number Filter is `equals`.

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

## Range Input Validation and Error States

When using the `inRange` filter type, the grid performs input validation to ensure the bounds of the range produce a valid filter; that is, where the start value is less than the end value.

Where this is not the case, the last edited input will display a red border and a hover tooltip directing the user to enter a valid value. While the filter is in an invalid state, the filter will not be applied. Screen readers that respond to the `aria-invalid` attribute or the `ValidityState` of the input will detect the input as invalid.

## Number Filter Values

By default, the values supplied to the Number 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/react-data-grid/value-getters/), but is specific to the filter.

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

A [Value Formatter](https://www.ag-grid.com/archive/36.2.0/react-data-grid/value-formatters/) that changes the number itself, such as one that rounds, leaves the column displaying one number and filtering on another, because the filter compares the value the grid holds rather than the formatted text. Return the displayed number from `filterValueGetter` and every filter option compares against that instead:

```jsx
const [columnDefs, setColumnDefs] = useState([
    {
        field: 'price',
        filter: 'agNumberColumnFilter',
        valueFormatter: ({ value }) => (value == null ? '' : value.toFixed(2)),
        filterValueGetter: ({ getValue }) => {
            const value = getValue('price');
            return value == null ? null : Number(value.toFixed(2));
        },
    }
]);

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

Where the displayed text is not itself a number, such as a currency, add `numberParser` to read what the user types and `numberFormatter` to write stored values back in the same form. The formatter gives the filter a `text` input on its own, so no `allowedCharPattern` is needed to make that text typeable — one would only narrow it, and a pattern omitting the symbols the formatter writes would stop the user typing them.

## Applying the Number Filter

Applying the Number 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/react-data-grid/filter-applying/#apply-clear-reset-and-cancel-buttons)
- [Applying the UI Model](https://www.ag-grid.com/archive/36.2.0/react-data-grid/filter-applying/#applying-the-ui-model)

## Blank Cells

If the row data contains blanks (i.e. `null`, `undefined`, or an empty or whitespace-only string), by default the row won't be included in filter results. To change this, use the filter params `includeBlanksInEquals`, `includeBlanksInNotEqual`, `includeBlanksInLessThan`, `includeBlanksInGreaterThan` and `includeBlanksInRange`. For example, the code snippet below configures a filter to include `null` for equals, but not for less than, greater than or in range (between):

```js
const filterParams = {
    includeBlanksInEquals: true,
    includeBlanksInNotEqual: false,
    includeBlanksInLessThan: false,
    includeBlanksInGreaterThan: false,
    includeBlanksInRange: false,
};
```

In the following example you can filter by age and see how blank values are included. Note the following:

- Column **Age** has both `null` and `undefined` values resulting in blank cells.
- Toggle the controls on the top to see how `includeBlanksInEquals`, `includeBlanksInNotEqual`, `includeBlanksInLessThan`, `includeBlanksInGreaterThan` and `includeBlanksInRange` impact the search result.

#### Number Null Filtering

```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,
  INumberFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  ValueGetterParams,
  enableDevValidations,
} from "ag-grid-community";

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

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

const originalColumnDefs: ColDef[] = [
  { field: "athlete" },
  {
    field: "age",
    maxWidth: 120,
    filter: "agNumberColumnFilter",
    filterParams: {
      includeBlanksInEquals: false,
      includeBlanksInNotEqual: false,
      includeBlanksInLessThan: false,
      includeBlanksInGreaterThan: false,
      includeBlanksInRange: false,
    } as INumberFilterParams,
  },
  {
    headerName: "Description",
    valueGetter: (params: ValueGetterParams) => `Age is ${params.data.age}`,
    minWidth: 340,
  },
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<any[]>([
    {
      athlete: "Alberto Gutierrez",
      age: 36,
    },
    {
      athlete: "Niall Crosby",
      age: 40,
    },
    {
      athlete: "Sean Landsman",
      age: null,
    },
    {
      athlete: "Robert Clarke",
      age: undefined,
    },
    {
      athlete: "Kirsten Flipkens",
      age: "",
    },
  ]);
  const [columnDefs, setColumnDefs] = useState<ColDef[]>(originalColumnDefs);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 100,
    };
  }, []);

  const updateParams = useCallback(
    (toChange: string) => {
      const value: boolean = (
        document.getElementById(`checkbox${toChange}`) as HTMLInputElement
      ).checked;
      originalColumnDefs[1].filterParams[`includeBlanksIn${toChange}`] = value;
      gridRef.current!.api.setGridOption("columnDefs", originalColumnDefs);
    },
    [originalColumnDefs],
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="test-container">
          <div className="test-header">
            <div className="test-label">
              Include NULL
              <br />
              in age:
            </div>
            <label>
              <input
                type="checkbox"
                id="checkboxEquals"
                onChange={() => updateParams("Equals")}
              />
              &nbsp;equals
            </label>
            <label>
              <input
                type="checkbox"
                id="checkboxNotEqual"
                onChange={() => updateParams("NotEqual")}
              />
              &nbsp;notEqual
            </label>
            <label>
              <input
                type="checkbox"
                id="checkboxLessThan"
                onChange={() => updateParams("LessThan")}
              />
              &nbsp;lessThan
            </label>
            <label>
              <input
                type="checkbox"
                id="checkboxGreaterThan"
                onChange={() => updateParams("GreaterThan")}
              />
              &nbsp;greaterThan
            </label>
            <label>
              <input
                type="checkbox"
                id="checkboxRange"
                onChange={() => updateParams("Range")}
              />
              &nbsp;inRange
            </label>
          </div>

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

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

[Live example: Number Null Filtering](https://www.ag-grid.com/archive/36.2.0/examples/filter-number/number-null-filtering/reactFunctionalTs/)

## Data Updates

The Number 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).
