---
title: "Floating Filter Component"
framework: vue
version: "36.1.0"
---

# Floating Filter Component

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

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import NumberFloatingFilterComponent from "./numberFloatingFilterComponentVue";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  TextFilterModule,
  ClientSideRowModelModule,
  NumberFilterModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :enableFilterHandlers="true"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    NumberFloatingFilterComponent,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<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 = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      filter: true,
      floatingFilter: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

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

## Implementing a Floating Filter Component

To configure custom floating filters, first enable the grid option `enableFilterHandlers`.

> **Note**
>
> If you do not enable the grid option `enableFilterHandlers`, it is still possible to use custom floating filters, however this is not recommended. See [Legacy Floating Filter Component](https://www.ag-grid.com/archive/36.1.0/vue-data-grid/component-floating-filter-legacy/).

When a Vue component is instantiated the grid will make the grid APIs, a number of utility methods as well as the cell and row values available to you via `this.params`.

The interface for a custom floating filter component is as follows:

```ts
interface FloatingFilterDisplay {
    // Mandatory methods

    // A hook to perform any necessary operations when the column definition is updated.
    refresh(params: FloatingFilterDisplayParams): void;

    // Optional methods

    // Gets called every time the popup is shown, after the GUI returned in
    // getGui is attached to the DOM. This is useful for any logic that requires attachment
    // before executing, such as putting focus on a particular DOM element.
    afterGuiAttached?(params?: IAfterGuiAttachedParams): void;

    // Gets called when the column is destroyed. If your custom filter needs to do
    // any resource cleaning up, do it here. A filter is NOT destroyed when it is
    // made 'not visible', as the GUI is kept to be shown again if the user selects
    // that filter again. The filter is destroyed when the column it is associated with is
    // destroyed, either when new columns are set into the grid, or the grid itself is destroyed.
    destroy?(): void;
}
```

### Custom Floating Filter Parameters

When a Vue component is instantiated the grid will make the grid APIs, a number of utility methods as well as the cell and row values available to you via `this.params` - the interface for what is provided is documented below.

If custom params are provided via the `colDef.floatingFilterComponentParams` property, these will be additionally added to the params object, overriding items of the same name if a name clash exists.

Properties available on the `FloatingFilterDisplayParams&lt;TData = any, TContext = any, TModel = any, TCustomParams = object&gt;` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `filterParams` | `TCustomParams` |  |  | 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. |
| `model` | `TModel \| null` |  |  | The current applied filter model for the column. |
| `onModelChange` | `Function` |  |  | Callback that should be called every time the model in the component changes. `additionalEventAttributes` If provided, will be passed to the filter changed event |
| `onUiChange` | `Function` |  |  | Callback that can be optionally called every time the floating filter UI changes. The grid will respond with emitting a FloatingFilterUiChangedEvent. Apart from emitting the event, the grid takes no further action. The callback takes one optional parameter which, if included, will get merged to the FloatingFilterUiChangedEvent object. |
| `getHandler` | `Function` |  |  | Get the filter handler instance. If using a `SimpleColumnFilter`, the handler is is a wrapper object containing the provided `doesFilterPass` callback. |
| `source` | `'init' \| 'ui' \| 'filter' \| 'api' \| 'colDef' \| 'dataChanged'` |  |  | 'init' \| 'ui' \| 'filter' \| 'api' \| 'colDef' \| 'dataChanged' |
| `column` | [`Column`](https://www.ag-grid.com/archive/36.1.0/vue-data-grid/column-object/) |  |  | The column this filter is for. |
| `showParentFilter` | `Function` |  |  | Shows the parent filter popup. |
| `api` | [`GridApi`](https://www.ag-grid.com/archive/36.1.0/vue-data-grid/grid-api/) |  |  | The grid api. |
| `context` | [`TContext`](https://www.ag-grid.com/archive/36.1.0/vue-data-grid/typescript-generics/#context-tcontext) |  |  | Application context as set on `gridOptions.context`. |

## 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

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CustomFilterModule,
  DoesFilterPassParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import NumberFilterComponent from "./numberFilterComponentVue";
import NumberFloatingFilterComponent from "./numberFloatingFilterComponentVue";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([ClientSideRowModelModule, CustomFilterModule]);

function doesFilterPass({
  node,
  model,
  handlerParams,
}: DoesFilterPassParams<any, any, number>): boolean {
  const value = handlerParams.getValue(node);
  if (value == null) {
    return true;
  }
  return value > model;
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :rowData="rowData"
      :enableFilterHandlers="true"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    NumberFilterComponent,
    NumberFloatingFilterComponent,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete" },
      {
        field: "gold",
        floatingFilterComponent: "NumberFloatingFilterComponent",
        floatingFilterComponentParams: {
          color: "gold",
        },
        filter: {
          component: "NumberFilterComponent",
          doesFilterPass: doesFilterPass,
        },
        suppressFloatingFilterButton: true,
      },
      {
        field: "silver",
        floatingFilterComponent: "NumberFloatingFilterComponent",
        floatingFilterComponentParams: {
          color: "silver",
        },
        filter: {
          component: "NumberFilterComponent",
          doesFilterPass: doesFilterPass,
        },
        suppressFloatingFilterButton: true,
      },
      {
        field: "bronze",
        floatingFilterComponent: "NumberFloatingFilterComponent",
        floatingFilterComponentParams: {
          color: "#CD7F32",
        },
        filter: {
          component: "NumberFilterComponent",
          doesFilterPass: doesFilterPass,
        },
        suppressFloatingFilterButton: true,
      },
      {
        field: "total",
        floatingFilterComponent: "NumberFloatingFilterComponent",
        floatingFilterComponentParams: {
          color: "unset",
        },
        filter: {
          component: "NumberFilterComponent",
          doesFilterPass: doesFilterPass,
        },
        suppressFloatingFilterButton: true,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      floatingFilter: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

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

## 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()` on the filter handler 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

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CustomFilterModule,
  FilterHandler,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import NumberFilterComponent from "./numberFilterComponentVue";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([CustomFilterModule, ClientSideRowModelModule]);

function numberFilterHandler(): FilterHandler<any, any, number> {
  return {
    doesFilterPass: ({ node, model, handlerParams }) => {
      const value = handlerParams.getValue(node);
      if (value == null) {
        return true;
      }
      return value > model;
    },
    getModelAsString: (model) => (model == null ? "" : ">" + model),
  };
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :enableFilterHandlers="true"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
    NumberFilterComponent,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", width: 150 },
      {
        field: "gold",
        width: 100,
        filter: {
          component: "NumberFilterComponent",
          handler: numberFilterHandler,
        },
        suppressHeaderMenuButton: true,
      },
      {
        field: "silver",
        width: 100,
        filter: {
          component: "NumberFilterComponent",
          handler: numberFilterHandler,
        },
        suppressHeaderMenuButton: true,
      },
      {
        field: "bronze",
        width: 100,
        filter: {
          component: "NumberFilterComponent",
          handler: numberFilterHandler,
        },
        suppressHeaderMenuButton: true,
      },
      {
        field: "total",
        width: 100,
        filter: {
          component: "NumberFilterComponent",
          handler: numberFilterHandler,
        },
        suppressHeaderMenuButton: true,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      floatingFilter: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        rowData.value = data;
      };

      fetch("https://www.ag-grid.com/example-assets/olympic-winners.json")
        .then((resp) => resp.json())
        .then((data) => updateData(data));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowData,
      onGridReady,
    };
  },
});

const app = createApp(VueExample);
app.mount("#app");
```

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