---
product: "AG Grid"
title: "Multi Filter"
description: "The Multi Filter allows multiple or to be used on the same column. This provides greater flexibility when filtering data in the grid."
enterprise: true
framework: vue
version: "36.2.0"
related:
    - title: "Text Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-text/"
    - title: "Number Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-number/"
    - title: "BigInt Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-bigint/"
    - title: "Date Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-date/"
    - title: "Set Filter"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-set/"
    - title: "Filter Conditions"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-conditions/"
    - title: "Applying Filters"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-applying/"
    - title: "Filter API"
      url: "https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-api/"
llms: "https://www.ag-grid.com/archive/36.2.0/llms.txt"
---

# Multi Filter

The Multi Filter allows multiple [Provided Filters](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filtering/#column-filter-types) or [Custom Filters](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/component-filter/) to be used on the same column. This provides greater flexibility when filtering data in the grid.

![Multi Filter](https://www.ag-grid.com/archive/36.2.0/_astro/multi-filter.DGQI2KU6.png)

## Enabling the Multi Filter

#### Multi Filter

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { MultiFilterModule, SetFilterModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

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

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"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", filter: "agMultiColumnFilter" },
      {
        field: "country",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "year",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "age",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
    });
    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: Multi Filter](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/multi-filter/vue3/)

To use a Multi Filter, specify the following in your Column Definition:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    // use the Multi Filter with default Text Filter and Set Filter
    { field: 'athlete', filter: 'agMultiColumnFilter' },
    // use the Multi Filter with Number Filter and Set Filter
    {
        field: 'year',
        filter: 'agMultiColumnFilter',
        filterParams: {
            filters: [
                {
                    filter: 'agNumberColumnFilter',
                },
                {
                    filter: 'agSetColumnFilter',
                },
            ],
        },
    },
];
```

By default the Multi Filter will show a [Text Filter](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-text/) and [Set Filter](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-set/), but you can specify which filters you would like to use in the `filters` array. The filters will be displayed in the same order as they are specified.

The example above shows the Multi Filter in action. Note the following:

- The **Athlete** column has a Multi Filter with default behaviour.
- The **Country** column has a Multi Filter with the child filters configured explicitly to match the default behaviour.
- The **Year** and **Age** columns have Multi Filters with the child filters configured explicitly to use the [Number Filter](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-number/) with the Set Filter.

## Passing Parameters to Child Filters

Parameters can be passed to child filters by specifying `filterParams` within the `filters` array of the Multi Filter params:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        field: 'athlete',
        filter: 'agMultiColumnFilter',
        filterParams: {
            filters: [
                {
                    filter: 'agTextColumnFilter',
                    // pass params to child filter
                    filterParams: {
                        defaultOption: 'startsWith',
                    },
                },
                {
                    filter: 'agSetColumnFilter',
                },
            ],
        },
    },
];
```

The example below demonstrates passing parameters to child filters:

- The Text Filter in the **Athlete** column has a different default option (`'startsWith'`).
- The [Date Filter](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-date/) in the **Date** column has a custom comparator to compare dates correctly.
- The Set Filter in the **Date** column has a custom comparator, so the values are displayed in ascending order.

#### Multi Filter Child Params

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateFilterModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IDateFilterParams,
  IMultiFilterParams,
  ISetFilterParams,
  ITextFilterParams,
  ModuleRegistry,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { MultiFilterModule, SetFilterModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  MultiFilterModule,
  SetFilterModule,
  TextFilterModule,
  DateFilterModule,
]);

const dateFilterParams: IMultiFilterParams = {
  filters: [
    {
      filter: "agDateColumnFilter",
      filterParams: {
        comparator: (filterDate: Date, cellValue: string) => {
          if (cellValue == null) return -1;
          return getDate(cellValue).getTime() - filterDate.getTime();
        },
      } as IDateFilterParams,
    },
    {
      filter: "agSetColumnFilter",
      filterParams: {
        comparator: (a: string, b: string) => {
          return getDate(a).getTime() - getDate(b).getTime();
        },
      } as ISetFilterParams,
    },
  ],
};

function getDate(value: string): Date {
  const dateParts = value.split("/");
  return new Date(
    Number(dateParts[2]),
    Number(dateParts[1]) - 1,
    Number(dateParts[0]),
  );
}

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"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              filterParams: {
                defaultOption: "startsWith",
              } as ITextFilterParams,
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "date",
        filter: "agMultiColumnFilter",
        filterParams: dateFilterParams,
      },
      { field: "country", filter: "agMultiColumnFilter" },
      { field: "sport", filter: "agMultiColumnFilter" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
    });
    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: Multi Filter Child Params](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/multi-filter-child-params/vue3/)

## Floating Filters

When [Floating Filters](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/floating-filters/) are used, the Floating Filter shown is for the child filter in the Multi Filter that was most recently applied and is still active. If no child filters are active, the Floating Filter for the first child filter in the Multi Filter is shown instead.

The example below shows Floating Filters enabled for all columns. Note how the Floating Filters change when you apply different child filters from the Multi Filter.

#### Floating Filters

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateFilterModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IDateFilterParams,
  IMultiFilterParams,
  ISetFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  NumberFilterModule,
  DateFilterModule,
  TextFilterModule,
]);

const dateFilterParams: IMultiFilterParams = {
  filters: [
    {
      filter: "agDateColumnFilter",
      filterParams: {
        comparator: (filterDate: Date, cellValue: string) => {
          if (cellValue == null) return -1;
          return getDate(cellValue).getTime() - filterDate.getTime();
        },
      } as IDateFilterParams,
    },
    {
      filter: "agSetColumnFilter",
      filterParams: {
        comparator: (a: string, b: string) => {
          return getDate(a).getTime() - getDate(b).getTime();
        },
      } as ISetFilterParams,
    },
  ],
};

function getDate(value: string) {
  const dateParts = value.split("/");
  return new Date(
    Number(dateParts[2]),
    Number(dateParts[1]) - 1,
    Number(dateParts[0]),
  );
}

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"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", filter: "agMultiColumnFilter" },
      {
        field: "gold",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "date",
        filter: "agMultiColumnFilter",
        filterParams: dateFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      floatingFilter: true,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: 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: Floating Filters](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/floating-filters/vue3/)

## Display Style

By default, all filters in the Multi Filter are shown inline in the same view, so that the user has easy, immediate access. However, you can change how filters are presented, by either using sub-menus or accordions to wrap each filter. To do this, you can set `display` to the style of how you would like a particular filter to be displayed:

```ts
<ag-grid-vue
    :columnDefs="columnDefs"
    /* other grid options ... */>
</ag-grid-vue>

this.columnDefs = [
    {
        field: 'athlete',
        filter: 'agMultiColumnFilter',
        filterParams: {
            filters: [
                {
                    filter: 'agTextColumnFilter',
                    display: 'subMenu',
                },
                {
                    filter: 'agSetColumnFilter',
                }
            ]
        }
    }
];
```

The options for `display` are `'inline'`, `'subMenu'` or `'accordion'`.

Please note that sub-menus will be shown as accordions in the Tool Panel.

You can also provide a title that will be used in the menu item or accordion title by using the `title` property.

The following example demonstrates the different display styles.

- The **Athlete** column demonstrates having the first filter inside a sub-menu.
- The sub-menu for the **Athlete** filter is shown as an accordion inside the Tool Panel.
- The **Country** column demonstrates having both filters as accordions.
- A custom title is used for the first filter in the **Country** column.
- The **Sport** column shows the default behaviour, where all filters are inline.

#### Display Style

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilterParams,
  ModuleRegistry,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  MultiFilterModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ClipboardModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  TextFilterModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :sideBar="sideBar"
      :rowData="rowData"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              display: "subMenu",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "country",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              display: "accordion",
              title: "Expand Me for Text Filters",
            },
            {
              filter: "agSetColumnFilter",
              display: "accordion",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "sport",
        filter: "agMultiColumnFilter",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const sideBar = ref<SideBarDef | string | string[] | boolean | null>({
      toolPanels: [
        {
          id: "filters",
          labelDefault: "Filters",
          labelKey: "filters",
          iconKey: "filter",
          toolPanel: "agFiltersToolPanel",
        },
      ],
    });
    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,
      sideBar,
      rowData,
      onGridReady,
    };
  },
});

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

[Live example: Display Style](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/display-style/vue3/)

## Custom Filters

You can use your own [Custom Filters](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/component-filter/) with the Multi Filter.

The example below shows a Custom Filter in use on the **Year** column, used alongside the grid-provided [Number Filter](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-number/).

#### Custom Filters

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DoesFilterPassParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  MultiFilterModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import YearFilter from "./YearFilterVue";
import YearFloatingFilter from "./YearFloatingFilterVue";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ClipboardModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  NumberFilterModule,
  TextFilterModule,
]);

function doesFilterPass({
  model,
  node,
  handlerParams,
}: DoesFilterPassParams<any, any, boolean>): boolean {
  return model ? handlerParams.getValue(node) > 2010 : true;
}

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,
    YearFilter,
    YearFloatingFilter,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", filter: "agMultiColumnFilter" },
      { field: "sport", filter: "agMultiColumnFilter" },
      {
        field: "year",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: {
                component: "YearFilter",
                doesFilterPass: doesFilterPass,
              },
              floatingFilterComponent: "YearFloatingFilter",
            },
            {
              filter: "agNumberColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      floatingFilter: true,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: 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 Filters](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/custom-filter/vue3/)

## Applying Multi Filters

Similar to [Applying Provided Filters](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/filter-applying/), the Multi Filter can have buttons that will control all the child filters together.

To configure buttons for the Multi Filter, first enable the grid option `enableFilterHandlers`. Note that if you have custom filter components, these will need to have been written to [Support Filter Handlers](https://www.ag-grid.com/archive/36.2.0/vue-data-grid/component-filter/#implementing-a-filter-component).

Note that when `enableFilterHandlers = true`, buttons can only be set against the parent Multi Filter parameters; they cannot be set against the individual child filters.

The following options can be specified on the `filterParams`:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `buttons` | `FilterAction[]` |  |  |  |
| `closeOnApply` | `boolean` |  |  |  |

#### Applying Multi Filters

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FilterWrapperParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import { MultiFilterModule, SetFilterModule } from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  MultiFilterModule,
  SetFilterModule,
  TextFilterModule,
  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,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", filter: "agMultiColumnFilter" },
      {
        field: "country",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "year",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "age",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      filterParams: {
        buttons: ["apply", "cancel"],
      } as FilterWrapperParams,
    });
    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: Applying Multi Filters](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/applying-multi-filters/vue3/)

## Multi Filter Model

The model for the Multi Filter wraps the models for all the child filters inside it. It has the `IMultiFilterModel` interface:

Properties available on the `IMultiFilterModel` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `filterType` | `'multi'` |  |  |  |
| `filterModels` | `any[] \| null` |  |  |  |

The `filterType` will always be set to `'multi'`. The models array is the same length as the number of child filters, containing the models for the child filters in the same order as the filters were specified in the `filterParams`. Each array entry will either be set to `null` if the corresponding child filter is not active, or to the current model for the child filter if it is active.

For example, if the Multi Filter has the default Text Filter and Set Filter, and the Set Filter is active, the Multi Filter model might look something like this:

```
const filterModel = {
    filterType: 'multi',
    filterModels: [
        null,
        { filterType: 'set', values: ['A', 'B', 'C'] }
    ]
}
```

The example below allows you to see the Multi Filter Model in use. You can print the current filter state to the console and save/restore it using the buttons at the top of the grid

#### Multi Filter Model

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateFilterModule,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IDateFilterParams,
  IMultiFilterParams,
  ISetFilterParams,
  ITextFilterParams,
  ModuleRegistry,
  NumberFilterModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  TextFilterModule,
  NumberFilterModule,
  DateFilterModule,
]);

const dateFilterParams: IMultiFilterParams = {
  filters: [
    {
      filter: "agDateColumnFilter",
      filterParams: {
        comparator: (filterDate: Date, cellValue: string) => {
          if (cellValue == null) return -1;
          return getDate(cellValue).getTime() - filterDate.getTime();
        },
      } as IDateFilterParams,
    },
    {
      filter: "agSetColumnFilter",
      filterParams: {
        comparator: (a: string, b: string) => {
          return getDate(a).getTime() - getDate(b).getTime();
        },
      } as ISetFilterParams,
    },
  ],
};

function getDate(value: string) {
  const dateParts = value.split("/");
  return new Date(
    Number(dateParts[2]),
    Number(dateParts[1]) - 1,
    Number(dateParts[0]),
  );
}

let savedFilterState: Record<string, any>;

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 1rem">
        <button v-on:click="printState()">Print State</button>
        <button v-on:click="saveState()">Save State</button>
        <button v-on:click="restoreState()">Restore State</button>
        <button v-on:click="resetState()">Reset State</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "athlete", filter: "agMultiColumnFilter" },
      {
        field: "country",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              filterParams: {
                defaultOption: "startsWith",
              } as ITextFilterParams,
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "gold",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agNumberColumnFilter",
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
      {
        field: "date",
        filter: "agMultiColumnFilter",
        filterParams: dateFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    function printState() {
      const filterState = gridApi.value!.getFilterModel();
      console.log("Current filter state: ", filterState);
    }
    function saveState() {
      savedFilterState = gridApi.value!.getFilterModel();
      console.log("Filter state saved");
    }
    function restoreState() {
      gridApi.value!.setFilterModel(savedFilterState);
      console.log("Filter state restored");
    }
    function resetState() {
      gridApi.value!.setFilterModel(null);
      console.log("Filter state reset");
    }
    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,
      printState,
      saveState,
      restoreState,
      resetState,
    };
  },
});

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

[Live example: Multi Filter Model](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/multi-filter-model/vue3/)

## Accessing Child Filters

The Multi Filter acts as a wrapper around a list of child filters inside it. The order of the filters is the same order as they are specified in the `filters` array in the `filterParams`. If you want to interact with the individual child filters, you can retrieve a particular child filter instance from the Multi Filter by calling `getChildFilterInstance(index)`, where `index` is the same as the index in the `filters` array. You can then call any API methods that are available on that particular child filter instance.

The example below shows how you can access child filter instances and call methods on them:

- Clicking the **Print Set Filter search text** button will access the Set Filter inside the Multi Filter and print the current search text to the console.

#### Accessing Child Filters

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilter,
  IMultiFilterParams,
  ITextFilterParams,
  ModuleRegistry,
  SetFilterUi,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";

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

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  ClipboardModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  TextFilterModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div class="example-wrapper">
      <div style="margin-bottom: 1rem">
        <button v-on:click="getSetMiniFilter()">Print Set Filter search text</button>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :rowData="rowData"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "athlete",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              filterParams: {
                buttons: ["apply", "clear"],
              } as ITextFilterParams,
            },
            {
              filter: "agSetColumnFilter",
            },
          ],
        } as IMultiFilterParams,
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 200,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const rowData = ref<IOlympicData[]>(null);

    function getSetMiniFilter() {
      gridApi
        .value!.getColumnFilterInstance<IMultiFilter>("athlete")
        .then((multiFilterInstance) => {
          const setFilter =
            multiFilterInstance!.getChildFilterInstance<SetFilterUi>(1)!;
          console.log(
            "Current Set Filter search text: ",
            setFilter.getMiniFilter(),
          );
        });
    }
    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,
      getSetMiniFilter,
    };
  },
});

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

[Live example: Accessing Child Filters](https://www.ag-grid.com/archive/36.2.0/examples/filter-multi/accessing-child-filters/vue3/)

## Multi Filter Parameters

Properties available on the `IMultiFilterParams` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `filters` | `IMultiFilterDef[]` |  |  |  |
| `readOnly` | `boolean` |  |  |  |

### IMultiFilterDef

Properties available on the `IMultiFilterDef` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `display` | `'inline' \| 'accordion' \| 'subMenu'` |  |  |  |
| `title` | `string` |  |  |  |
| `filter` | `IFilterType \| ColumnFilter` |  |  |  |
| `filterParams` | `any` |  |  |  |
| `floatingFilterComponent` | `IFloatingFilterType` |  |  |  |
| `floatingFilterComponentParams` | `any` |  |  |  |
| `filterValueGetter` | `string \| ValueGetterFunc` |  |  |  |

## Multi Filter API

Properties available on the `IMultiFilterComp` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `isFilterActive` | `Function` |  |  |  |
| `getModel` | `Function` |  |  |  |
| `setModel` | `Function` |  |  |  |
| `getChildFilterInstance` | `Function` |  |  |  |
