---
title: "Set Filter - API"
enterprise: true
framework: react
version: "36.1.0"
---

# Set Filter - API

This section describes how the Set Filter can be controlled programmatically using API calls.

## Set Filter Model

Get and set the state of the Set Filter by getting and setting the model on the grid API.

```js
// get filter model
const model = api.getColumnFilterModel('country');

// set filter model and update
await api.setColumnFilterModel('country', { values: ['Spain', 'Ireland', 'South Africa'] });

// refresh rows based on the filter (not automatic to allow for batching multiple filters)
api.onFilterChanged();
```

The filter model contains an array of string values where each item in the array corresponds to an element to be selected from the set.

Properties available on the `SetFilterModel` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `filterType` | `'set'` |  |  | 'set' |
| `values` | `SetFilterModelValue` |  |  | SetFilterModelValue |

When values are taken from the grid (the default, with no `filterParams.values` supplied), the model is reconciled against the values currently in the data when it is set. Any selected values that are not present are dropped and not retained: if those values later appear in the data they are not re-selected. Supply `filterParams.values` to keep selections for values that are not currently in the data. See [Refreshing Values](https://www.ag-grid.com/react-data-grid/filter-set-filter-list/#refreshing-values) and the [Excel Mode](https://www.ag-grid.com/react-data-grid/filter-set-excel-mode/) comparison.

> **Note**
>
> This value-level reconciliation is distinct from `setFilterModel` being applied asynchronously when inferring cell data types. With initially empty row data, the cell data types cannot be resolved, so the whole `setFilterModel` call is deferred until row data is added (set `cellDataType` to `false` or to an explicit value on every column to apply it synchronously). That defers the entire call once; it does not retain individual values that are absent from the data.

## Set Filter API

The Set Filter consists of two parts - the Set Filter UI (the UI component) and the Set Filter Handler (maintains the values and performs the filter logic).

Note that the Set Filter will always use a filter handler, regardless of whether `enableFilterHandlers` is enabled (which controls filter handlers for [Custom Filter Components](https://www.ag-grid.com/react-data-grid/component-filter/)).

The Set Filter values can be updated via the Set Filter Handler:

```jsx
// get filter handler
const countryFilterHandler = gridApi.getColumnFilterHandler('country');
```

The `SetFilterHandler` interface defines the public API for the Set Filter Handler.

Properties available on the `SetFilterHandler&lt;TValue = string&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getFilterKeys` | `Function` |  |  | Returns the full list of unique keys used by the Set Filter. |
| `getFilterValues` | `Function` |  |  | Returns the full list of unique values used by the Set Filter. |
| `setFilterValues` | `Function` |  |  | Sets the values used in the Set Filter on the fly. |
| `refreshFilterValues` | `Function` |  |  | Refreshes the values shown in the filter from the original source. For example, if a callback was provided, the callback will be executed again and the filter will refresh using the values returned. |
| `resetFilterValues` | `Function` |  |  | Resets the Set Filter to use values from the grid, rather than any values that have been provided directly. |

The Mini Filter can be interacted with via the Set Filter UI instance:

```jsx
// get filter UI instance
gridApi.getColumnFilterInstance('country').then(countryFilterComponent => {
    // use set filter UI instance
});
```

The `SetFilterUi` interface defines the public API for the Set Filter UI component.

Properties available on the `SetFilterUi&lt;TValue = string&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `getMiniFilter` | `Function` |  |  | Returns the current mini-filter text. |
| `setMiniFilter` | `Function` |  |  | Sets the text in the Mini Filter at the top of the filter (the 'quick search' in the popup). |
| `getFilterHandler` | `Function` |  |  | Returns the corresponding Set Filter Handler. |

In the example below, you can see how the filter for the Athlete column is modified through the API.

#### Set Filter API

```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,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ISetFilterParams,
  KeyCreatorParams,
  ModuleRegistry,
  NumberFilterModule,
  SetFilterHandler,
  SideBarDef,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

function countryKeyCreator(params: KeyCreatorParams) {
  return params.value.name;
}

function patchData(data: any[]) {
  // hack the data, replace each country with an object of country name and code
  data.forEach((row) => {
    const countryName = row.country;
    const countryCode = countryName.substring(0, 2).toUpperCase();
    row.country = {
      name: countryName,
      code: countryCode,
    };
  });
}

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);
  const [rowData, setRowData] = useState<IOlympicData[]>();
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
      field: "athlete",
      filter: "agSetColumnFilter",
    },
    {
      field: "country",
      valueFormatter: (params: ValueFormatterParams) => {
        return `${params.value.name} (${params.value.code})`;
      },
      keyCreator: countryKeyCreator,
      filterParams: {
        valueFormatter: (params: ValueFormatterParams) => params.value.name,
      } as ISetFilterParams,
    },
    { field: "age", maxWidth: 120, filter: "agNumberColumnFilter" },
    { field: "year", maxWidth: 120 },
    { field: "date" },
    { field: "sport" },
    { field: "gold", filter: "agNumberColumnFilter" },
    { field: "silver", filter: "agNumberColumnFilter" },
    { field: "bronze", filter: "agNumberColumnFilter" },
    { field: "total", filter: "agNumberColumnFilter" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 160,
      filter: true,
    };
  }, []);

  const onGridReady = useCallback((params: GridReadyEvent) => {
    fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
      .then((resp) => resp.json())
      .then((data: IOlympicData[]) => {
        patchData(data);
        setRowData(data);
      });
  }, []);

  const onFirstDataRendered = useCallback((params: FirstDataRenderedEvent) => {
    params.api.getToolPanelInstance("filters")!.expandFilters();
  }, []);

  const selectJohnAndKenny = useCallback(() => {
    gridRef
      .current!.api.setColumnFilterModel("athlete", {
        values: ["John Joe Nevin", "Kenny Egan"],
      })
      .then(() => {
        gridRef.current!.api.onFilterChanged();
      });
  }, []);

  const selectEverything = useCallback(() => {
    gridRef.current!.api.setColumnFilterModel("athlete", null).then(() => {
      gridRef.current!.api.onFilterChanged();
    });
  }, []);

  const selectNothing = useCallback(() => {
    gridRef
      .current!.api.setColumnFilterModel("athlete", { values: [] })
      .then(() => {
        gridRef.current!.api.onFilterChanged();
      });
  }, []);

  const setCountriesToFranceAustralia = useCallback(() => {
    const handler = gridRef.current!.api.getColumnFilterHandler<
      SetFilterHandler<{
        name: string;
        code: string;
      }>
    >("country");
    handler!.setFilterValues([
      {
        name: "France",
        code: "FR",
      },
      {
        name: "Australia",
        code: "AU",
      },
    ]);
  }, []);

  const setCountriesToAll = useCallback(() => {
    const handler = gridRef.current!.api.getColumnFilterHandler<
      SetFilterHandler<{
        name: string;
        code: string;
      }>
    >("country");
    handler!.resetFilterValues();
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div className="example-header">
            <div>
              Athlete:
              <button onClick={selectNothing}>API: Filter empty set</button>
              <button onClick={selectJohnAndKenny}>
                API: Filter only John Joe Nevin and Kenny Egan
              </button>
              <button onClick={selectEverything}>API: Remove filter</button>
            </div>
            <div style={{ paddingTop: "10px" }}>
              Country - available filter values
              <button onClick={setCountriesToFranceAustralia}>
                Filter values restricted to France and Australia
              </button>
              <button onClick={setCountriesToAll}>
                Make all countries available
              </button>
            </div>
          </div>

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

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

[Live example: Set Filter API](https://www.ag-grid.com/examples/filter-set-api/set-filter-api/reactFunctionalTs)

### Enabling Case-Sensitivity

By default the API is case-insensitive. You can enable case sensitivity by using the `caseSensitive: true` filter parameter:

```jsx
const [columnDefs, setColumnDefs] = useState([
    {
        field: 'colour',
        filter: 'agSetColumnFilter',
        filterParams: {
            caseSensitive: true
        }
    }
]);

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

> **Note**
>
> The `caseSensitive` option also affects [Mini-Filter](https://www.ag-grid.com/react-data-grid/filter-set-mini-filter/#enabling-case-sensitive-searches) searches and the values presented in the [Filter List](https://www.ag-grid.com/react-data-grid/filter-set-filter-list/#enabling-value-case-sensitivity).

The following example demonstrates the difference in behaviour between `caseSensitive: false` (the default) and `caseSensitive: true`:

- With `caseSensitive: false` (the default):
  - `setModel()` will perform **case-insensitive** matching against available values to decide what is enabled in the Filter List.
  - `setFilterValues()` will override the available values and force the case of the presented values in the Filter List to those provided.
    - Selected values will be maintained based upon **case-insensitive** matching.
- With `caseSensitive: true`:
  - `setModel()` will perform **case-sensitive** matching against available values to decide what is enabled in the Filter List.
  - `setFilterValues()` will override the available values and force the case of the presented values in the Filter List to those provided.
    - Selected values will be maintained based upon **case-sensitive** matching.
- In both cases `getModel()` and `getFilterValues()` will return the values with casing that matches those displayed in the Filter List. This is printed to the developer console.

#### Set Filter API - Case Sensitivity

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

import type {
  ColDef,
  FirstDataRenderedEvent,
  SetFilterHandler,
} from "ag-grid-community";
import {
  ClientSideRowModelModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import type { CustomCellRendererProps } from "ag-grid-react";
import { AgGridProvider, AgGridReact } from "ag-grid-react";

import { getData } from "./data";
import "./styles.css";

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

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

const colourCellRenderer = (props: CustomCellRendererProps) => {
  if (!props.value || props.value === "(Select All)") {
    return props.value;
  }

  const styles = {
    verticalAlign: "middle",
    border: "1px solid black",
    margin: 3,
    display: "inline-block",
    width: 10,
    height: 10,
    backgroundColor: props.value.toLowerCase(),
  };
  return (
    <React.Fragment>
      <div style={styles} />
      {props.value}
    </React.Fragment>
  );
};

const FILTER_TYPES: Record<string, string> = {
  insensitive: "colour",
  sensitive: "colour_1",
};

const MANGLED_COLOURS = ["ReD", "OrAnGe", "WhItE", "YeLlOw"];

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(getData());
  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    {
      headerName: "Case Insensitive (default)",
      field: "colour",
      filter: "agSetColumnFilter",
      filterParams: {
        caseSensitive: false,
        cellRenderer: colourCellRenderer,
      },
    },
    {
      headerName: "Case Sensitive",
      field: "colour",
      filter: "agSetColumnFilter",
      filterParams: {
        caseSensitive: true,
        cellRenderer: colourCellRenderer,
      },
    },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 225,
      cellRenderer: colourCellRenderer,
      floatingFilter: true,
    };
  }, []);

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

  const setModel = useCallback((type: string) => {
    gridRef
      .current!.api.setColumnFilterModel(FILTER_TYPES[type], {
        values: MANGLED_COLOURS,
      })
      .then(() => {
        gridRef.current!.api.onFilterChanged();
      });
  }, []);

  const getModel = useCallback((type: string) => {
    console.log(
      JSON.stringify(
        gridRef.current!.api.getColumnFilterModel(FILTER_TYPES[type]),
        null,
        2,
      ),
    );
  }, []);

  const setFilterValues = useCallback((type: string) => {
    const handler =
      gridRef.current!.api.getColumnFilterHandler<SetFilterHandler>(
        FILTER_TYPES[type],
      );
    handler!.setFilterValues(MANGLED_COLOURS);
  }, []);

  const getValues = useCallback((type: string) => {
    const handler =
      gridRef.current!.api.getColumnFilterHandler<SetFilterHandler>(
        FILTER_TYPES[type],
      );
    console.log(JSON.stringify(handler!.getFilterValues(), null, 2));
  }, []);

  const reset = useCallback((type: string) => {
    const handler =
      gridRef.current!.api.getColumnFilterHandler<SetFilterHandler>(
        FILTER_TYPES[type],
      );
    handler!.resetFilterValues();
    gridRef
      .current!.api.setColumnFilterModel(FILTER_TYPES[type], null)
      .then(() => {
        gridRef.current!.api.onFilterChanged();
      });
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div className="example-header">
            <div>
              Case Insensitive:
              <button onClick={() => setModel("insensitive")}>
                API: setModel() - mismatching case
              </button>
              <button onClick={() => getModel("insensitive")}>
                API: getModel()
              </button>
              <button onClick={() => setFilterValues("insensitive")}>
                API: setFilterValues() - mismatching case
              </button>
              <button onClick={() => getValues("insensitive")}>
                API: getFilterValues()
              </button>
              <button onClick={() => reset("insensitive")}>Reset</button>
            </div>
            <div style={{ paddingTop: "10px" }}>
              Case Sensitive:
              <button onClick={() => setModel("sensitive")}>
                API: setModel() - mismatching case
              </button>
              <button onClick={() => getModel("sensitive")}>
                API: getModel()
              </button>
              <button onClick={() => setFilterValues("sensitive")}>
                API: setFilterValues() - mismatching case
              </button>
              <button onClick={() => getValues("sensitive")}>
                API: getFilterValues()
              </button>
              <button onClick={() => reset("sensitive")}>Reset</button>
            </div>
          </div>

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

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

[Live example: Set Filter API - Case Sensitivity](https://www.ag-grid.com/examples/filter-set-api/set-filter-api-case-sensitive/reactFunctionalTs)
