---
title: "SSRM Filtering"
enterprise: true
framework: vue
version: "36.1.0"
---

# SSRM Filtering

This section covers Filtering using the Server-Side Row Model (SSRM).

## Enabling Filtering

Filtering is enabled in the grid via the `filter` column definition attribute.

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

this.columnDefs = [
    // sets the 'text' filter
    { field: 'country', filter: 'agTextColumnFilter' },

    // use the default 'set' filter
    { field: 'year', filter: true },

    // no filter (unspecified)
    { field: 'sport' },
];
```

For more details on filtering configurations see the section on [Column Filtering](https://www.ag-grid.com/vue-data-grid/filtering/).

## Server-side Filtering

The actual filtering of rows is performed on the server when using the Server-Side Row Model. When a filter is applied in the grid a request is made for more rows via `getRows(params)` on the [Server-Side Datasource](https://www.ag-grid.com/vue-data-grid/server-side-model-datasource/). The supplied params includes a request containing filter metadata contained in the `filterModel` property.

The request object sent to the server contains filter metadata in the `filterModel` property, an example is shown below:

```js
// Example request with filter info
{
    filterModel: {
        athlete: {
            filterType: 'text',
            type: 'contains',
            filter: 'fred'
        },
        year: {
            filterType: 'number',
            type: 'greaterThan',
            filter: 2005,
            filterTo: null
        }
    },

    // other properties
}
```

Notice in the snippet above the `filterModel` object contains a `'text'` and `'number'` filter. This filter metadata is used by the server to perform the filtering.

For more details on properties and values used in these filters see the sections on [Text Filter Model](https://www.ag-grid.com/vue-data-grid/filter-text/#text-filter-model) and [Number Filter Model](https://www.ag-grid.com/vue-data-grid/filter-number/#number-filter-model).

The example below demonstrates filtering using Simple Column Filters, note the following:

- The **Athlete** column has a `'text'` filter defined using `filter: 'agTextColumnFilter'`.
- The **Year** column has a `'number'` filter defined using `filter: 'agNumberColumnFilter'`.
- The medals columns have a `'number'` filter defined using `filter: 'agNumberColumnFilter'` on the `'number'` column type.
- The server uses the metadata contained in the `filterModel` to filter the rows.
- Open the browser's dev console to view the `filterModel` supplied in the request to the datasource.

#### Server-Side Filtering

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ColDef,
  ColGroupDef,
  ColTypeDefs,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IServerSideDatasource,
  ModuleRegistry,
  NumberFilterModule,
  RowModelType,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ColumnMenuModule,
  ContextMenuModule,
  ServerSideRowModelModule,
  TextFilterModule,
  NumberFilterModule,
]);

function getServerSideDatasource(server: any): IServerSideDatasource {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);
      // get data for request from our fake server
      const response = server.getData(params.request);
      // simulating real server call with a 500ms delay
      setTimeout(() => {
        if (response.success) {
          // supply rows for requested block to grid
          params.success({
            rowData: response.rows,
            rowCount: response.lastRow,
          });
        } else {
          params.fail();
        }
      }, 500);
    },
  };
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :columnTypes="columnTypes"
      :rowModelType="rowModelType"
      :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: "agTextColumnFilter",
        minWidth: 220,
      },
      {
        field: "year",
        filter: "agNumberColumnFilter",
        filterParams: {
          buttons: ["reset"],
          debounceMs: 1000,
          maxNumConditions: 1,
        },
      },
      { field: "gold", type: "number" },
      { field: "silver", type: "number" },
      { field: "bronze", type: "number" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const columnTypes = ref<ColTypeDefs>({
      number: { filter: "agNumberColumnFilter" },
    });
    const rowModelType = ref<RowModelType>("serverSide");
    const rowData = ref<IOlympicData[]>(null);

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

      const updateData = (data) => {
        // setup the fake server with entire dataset
        const fakeServer = new FakeServer(data);
        // create datasource with a reference to the fake server
        const datasource = getServerSideDatasource(fakeServer);
        // register the datasource with the grid
        params.api!.setGridOption("serverSideDatasource", datasource);
      };

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

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

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

[Live example: Server-Side Filtering](https://www.ag-grid.com/examples/server-side-model-filtering/infinite-simple/vue3)

## Date Filters

For more details on Date Filter model properties and available options see [Date Filter](https://www.ag-grid.com/vue-data-grid/filter-date/) and [Filter Model](https://www.ag-grid.com/vue-data-grid/filter-date/#filter-model).

### Preset Date Range Filters

When using a Date Filter with built-in date ranges (for example, Today or Last 7 Days), the Grid State model and the SSRM request model are identical. Both use the preset `type` and leave `dateFrom` and `dateTo` as `undefined`. Your server (or custom filtering code) must interpret the preset and apply the equivalent date range logic using its own time zone and locale rules.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `type` | `ISimpleFilterModelPresetType` |  |  | Preset range type (for example, `today` or `last7Days`). |
| `dateFrom` | `undefined` |  |  | Preset range does not provide an explicit `from` date. |
| `dateTo` | `undefined` |  |  | Preset range does not provide an explicit `to` date. |
| `filterType` | `'date'` |  |  | Filter type is always `'date'` |

## Set Filtering

Filtering using the [Set Filter](https://www.ag-grid.com/vue-data-grid/filter-set/) has a few differences to filtering with Simple Filters.

### Set Filter Model

Entries in the `filterModel` have a different format to the Simple Filters. This filter model is what gets passed as part of the request to the server when using Server-side Filtering. The following shows an example of a Set Filter where two items are selected:

```js
// IServerSideGetRowsRequest
{
    filterModel: {
        country: {
            filterType: 'set',
            values: ['Australia', 'Belgium']
        }
    },

    // other properties
}
```

### Set Filter Values

When using the Set Filter with the SSRM it is necessary to supply the values as the grid does not have all rows loaded. This can be done either synchronously or asynchronously using the `values` filter param as shown below:

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

this.columnDefs = [
    // colDef with Set Filter values supplied synchronously
    {
        field: 'country',
        filter: 'agSetColumnFilter',
        filterParams: {
            values: ['Australia', 'China', 'Sweden']
        }
    },
    // colDef with Set Filter values supplied asynchronously
    {
        field: 'country',
        filter: 'agSetColumnFilter',
        filterParams: {
            values: params => {
                // simulating async delay
                setTimeout(() => params.success(['Australia', 'China', 'Sweden']), 500);
            }
        }
    }
];
```

For more details on setting values, see [Supplying Filter Values](https://www.ag-grid.com/vue-data-grid/filter-set-filter-list/#supplying-filter-values). Once you have supplied values to the Set Filter, they will not change unless you ask for them to be refreshed. See [Refreshing Values](https://www.ag-grid.com/vue-data-grid/filter-set-filter-list/#refreshing-values) for more information.

The example below demonstrates Server-side Filtering using the Set Filter. Note the following:

- The **Country** column has a Set Filter defined using `filter: 'agSetColumnFilter'`.
- The **Sport** column has a [Multi Filter](https://www.ag-grid.com/vue-data-grid/filter-multi/) defined using `filter: 'agMultiColumnFilter'`, it combines a Set Filter and a [Text Filter](https://www.ag-grid.com/vue-data-grid/filter-text/).
- Set Filter values are fetched asynchronously and supplied via the `params.success(values)` callback.
- The filter for the **Country** column is using [complex objects](https://www.ag-grid.com/vue-data-grid/filter-set-filter-list/#complex-objects). The country name is shown in the Filter List, but the `filterModel` (and request) use the country code.
- The filter for the **Sport** column only shows the values which are available for the selected countries. When the filter for the **Country** column is changed, the values for the **Sport** filter are updated.
- The server uses the metadata contained in the `filterModel` to filter the rows.
- Open the browser's dev console to view the `filterModel` supplied in the request to the datasource.

#### Set Filter Server-Side Filtering

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IMultiFilter,
  IServerSideDatasource,
  KeyCreatorParams,
  ModuleRegistry,
  RowModelType,
  SetFilterHandler,
  SetFilterUi,
  SetFilterValuesFuncParams,
  TextFilterModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  ServerSideRowModelModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

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

function countryCodeKeyCreator(params: KeyCreatorParams): string {
  return params.value.code;
}

function countryValueFormatter(params: ValueFormatterParams): string {
  return params.value.name;
}

function countryComparator(
  a: {
    name: string;
    code: string;
  },
  b: {
    name: string;
    code: string;
  },
): number {
  // for complex objects, need to provide a comparator to choose what to sort by
  if (a.name < b.name) {
    return -1;
  } else if (a.name > b.name) {
    return 1;
  }
  return 0;
}

let fakeServer: any;

let selectedCountries: string[] | null = null;

let textFilterStored: string[] | null = null;

export function areEqual(
  a: readonly any[] | null | undefined,
  b: readonly any[] | null | undefined,
): boolean {
  if (a === b) {
    return true; // Same instance, no need to compare
  }
  if (!a || !b) {
    return a == null && b == null;
  }
  const len = a.length;
  if (len !== b.length) {
    return false;
  }
  for (let i = 0; i < len; i++) {
    if (a[i] !== b[i]) {
      return false;
    }
  }
  return true;
}

function getCountryValuesAsync(params: SetFilterValuesFuncParams) {
  const sportFilterModel = params.api.getFilterModel()["sport"];
  const countries = fakeServer.getCountries(sportFilterModel);
  // simulating real server call with a 500ms delay
  setTimeout(() => {
    params.success(countries);
  }, 500);
}

function getSportValuesAsync(params: SetFilterValuesFuncParams) {
  const sportFilterModel = params.api.getFilterModel()["sport"];
  const sports = fakeServer.getSports(selectedCountries, sportFilterModel);
  // simulating real server call with a 500ms delay
  setTimeout(() => {
    params.success(sports);
  }, 500);
}

function getServerSideDatasource(server: any): IServerSideDatasource {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);
      // get data for request from our fake server
      const response = server.getData(params.request);
      // simulating real server call with a 500ms delay
      setTimeout(() => {
        if (response.success) {
          // supply rows for requested block to grid
          params.success({
            rowData: response.rows,
            rowCount: response.lastRow,
          });
        } else {
          params.fail();
        }
      }, 500);
    },
  };
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :rowModelType="rowModelType"
      :cacheBlockSize="cacheBlockSize"
      :maxBlocksInCache="maxBlocksInCache"
      :rowData="rowData"
      @filter-changed="onFilterChanged"></ag-grid-vue>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi<IOlympicData> | null>(null);
    const columnDefs = ref<ColDef[]>([
      {
        field: "country",
        filter: "agSetColumnFilter",
        valueFormatter: countryValueFormatter,
        filterParams: {
          values: getCountryValuesAsync,
          keyCreator: countryCodeKeyCreator,
          valueFormatter: countryValueFormatter,
          comparator: countryComparator,
          suppressClearModelOnRefreshValues: true,
          buttons: ["apply"],
        },
      },
      {
        field: "sport",
        filter: "agMultiColumnFilter",
        filterParams: {
          filters: [
            {
              filter: "agTextColumnFilter",
              filterParams: {
                defaultOption: "startsWith",
              },
            },
            {
              filter: "agSetColumnFilter",
              filterParams: {
                values: getSportValuesAsync,
                suppressClearModelOnRefreshValues: true,
              },
            },
          ],
        },
        menuTabs: ["filterMenuTab"],
      },
      { field: "athlete" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 150,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const rowModelType = ref<RowModelType>("serverSide");
    const cacheBlockSize = ref(100);
    const maxBlocksInCache = ref(10);
    const rowData = ref<IOlympicData[]>(null);

    function onFilterChanged() {
      const countryFilterModel = gridApi.value!.getFilterModel()["country"];
      const sportFilterModel = gridApi.value!.getFilterModel()["sport"];
      const selected = countryFilterModel && countryFilterModel.values;
      const textFilter = sportFilterModel?.filterModels[0]
        ? sportFilterModel.filterModels[0]
        : null;
      if (
        !areEqual(selectedCountries, selected) ||
        !areEqual(textFilterStored, textFilter)
      ) {
        selectedCountries = selected;
        textFilterStored = textFilter;
        console.log("Refreshing sports filter");
        // By default, the Multi Filter does not use a filter handler, so retrieve via `getColumnFilterInstance`.
        // If using `enableFilterHandlers = true`, the Multi Filter handler can be retrieved via `getColumnFilterHandler`.
        gridApi.value
          .getColumnFilterInstance<IMultiFilter>("sport")
          .then((filter) => {
            filter!
              .getChildFilterInstance<SetFilterUi>(1)!
              .getFilterHandler()
              .refreshFilterValues();
          });
        gridApi.value
          .getColumnFilterHandler<SetFilterHandler>("country")!
          .refreshFilterValues();
      }
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      const updateData = (data) => {
        // we don't have unique codes in our dataset, so generate unique ones
        const namesToCodes: Map<string, string> = new Map();
        const codesToNames: Map<string, string> = new Map();
        data.forEach((row: any) => {
          row.countryName = row.country;
          if (namesToCodes.has(row.countryName)) {
            row.countryCode = namesToCodes.get(row.countryName);
          } else {
            row.countryCode = row.country.substring(0, 2).toUpperCase();
            if (codesToNames.has(row.countryCode)) {
              let num = 0;
              do {
                row.countryCode = `${row.countryCode[0]}${num++}`;
              } while (codesToNames.has(row.countryCode));
            }
            codesToNames.set(row.countryCode, row.countryName);
            namesToCodes.set(row.countryName, row.countryCode);
          }
          delete row.country;
        });
        // setup the fake server with entire dataset
        fakeServer = new FakeServer(data);
        // create datasource with a reference to the fake server
        const datasource = getServerSideDatasource(fakeServer);
        // register the datasource with the grid
        params.api!.setGridOption("serverSideDatasource", datasource);
      };

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

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      rowModelType,
      cacheBlockSize,
      maxBlocksInCache,
      rowData,
      onGridReady,
      onFilterChanged,
    };
  },
});

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

[Live example: Set Filter Server-Side Filtering](https://www.ag-grid.com/examples/server-side-model-filtering/infinite-set/vue3)

## Batching Filter Requests

The [New Filters Tool Panel](https://www.ag-grid.com/vue-data-grid/tool-panel-filters-new/) allows for filter changes to be batched together before a new `getRows` request is sent to the datasource.

This is possible by configuring the New Filters Tool Panel to [Use Buttons](https://www.ag-grid.com/vue-data-grid/tool-panel-filters-new/#using-buttons). Each filter can then be edited in the tool panel, and one request will be sent when the global apply button is clicked.

#### Batching Filter Requests

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ColDef,
  ColGroupDef,
  FilterWrapperParams,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IServerSideDatasource,
  ModuleRegistry,
  NumberFilterModule,
  RowModelType,
  SideBarDef,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ContextMenuModule,
  NewFiltersToolPanelModule,
  ServerSideRowModelModule,
  SideBarModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ColumnMenuModule,
  ContextMenuModule,
  ServerSideRowModelModule,
  TextFilterModule,
  NumberFilterModule,
  SideBarModule,
  NewFiltersToolPanelModule,
]);

function getServerSideDatasource(server: any): IServerSideDatasource {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);
      // get data for request from our fake server
      const response = server.getData(params.request);
      // simulating real server call with a 500ms delay
      setTimeout(() => {
        if (response.success) {
          // supply rows for requested block to grid
          params.success({
            rowData: response.rows,
            rowCount: response.lastRow,
          });
        } else {
          params.fail();
        }
      }, 500);
    },
  };
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :rowModelType="rowModelType"
      :enableFilterHandlers="true"
      :suppressSetFilterByDefault="true"
      :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",
        cellDataType: "text",
        minWidth: 220,
      },
      { field: "year", cellDataType: "number" },
      { field: "gold", cellDataType: "number" },
      { field: "silver", cellDataType: "number" },
      { field: "bronze", cellDataType: "number" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      filter: true,
      filterParams: {
        buttons: ["apply"], // set all filters to use buttons
      } as FilterWrapperParams,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const rowModelType = ref<RowModelType>("serverSide");
    const sideBar = ref<SideBarDef | string | string[] | boolean | null>({
      toolPanels: [
        {
          id: "filters-new",
          labelDefault: "Filters",
          labelKey: "filters",
          iconKey: "filter",
          toolPanel: "agNewFiltersToolPanel",
          toolPanelParams: {
            buttons: ["reset", "apply"],
          },
        },
      ],
      defaultToolPanel: "filters-new",
    });
    const rowData = ref<IOlympicData[]>(null);

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

      const updateData = (data) => {
        // setup the fake server with entire dataset
        const fakeServer = new FakeServer(data);
        // create datasource with a reference to the fake server
        const datasource = getServerSideDatasource(fakeServer);
        // register the datasource with the grid
        params.api!.setGridOption("serverSideDatasource", datasource);
      };

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

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

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

[Live example: Batching Filter Requests](https://www.ag-grid.com/examples/server-side-model-filtering/global-apply/vue3)

## Advanced Filter

In addition to Column Filters, the [Advanced Filter](https://www.ag-grid.com/vue-data-grid/filter-advanced/) can also be used with the Server-Side Row Model. In this case, the `filterModel` in the request will be an [Advanced Filter Model](https://www.ag-grid.com/vue-data-grid/filter-advanced/#filter-model--api) of type `AdvancedFilterModel | null`.

#### Advanced Filter

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import {
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  GridReadyEvent,
  IServerSideDatasource,
  ModuleRegistry,
  NumberFilterModule,
  RowModelType,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  AdvancedFilterModule,
  ColumnMenuModule,
  ContextMenuModule,
  ServerSideRowModelModule,
} from "ag-grid-enterprise";
import { FakeServer } from "./fakeServer";
import { IOlympicData } from "./interfaces";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  TextFilterModule,
  NumberFilterModule,
  AdvancedFilterModule,
  ColumnMenuModule,
  ContextMenuModule,
  ServerSideRowModelModule,
]);

function getServerSideDatasource(server: any): IServerSideDatasource {
  return {
    getRows: (params) => {
      console.log("[Datasource] - rows requested by grid: ", params.request);
      // get data for request from our fake server
      const response = server.getData(params.request);
      // simulating real server call with a 500ms delay
      setTimeout(() => {
        if (response.success) {
          // supply rows for requested block to grid
          params.success({
            rowData: response.rows,
            rowCount: response.lastRow,
          });
        } else {
          params.fail();
        }
      }, 500);
    },
  };
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <ag-grid-vue
      style="width: 100%; height: 100%;"
      @grid-ready="onGridReady"
      :columnDefs="columnDefs"
      :defaultColDef="defaultColDef"
      :rowModelType="rowModelType"
      :enableAdvancedFilter="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",
        cellDataType: "text",
        minWidth: 220,
      },
      {
        field: "year",
        cellDataType: "number",
      },
      {
        field: "gold",
        cellDataType: "number",
      },
      {
        field: "silver",
        cellDataType: "number",
      },
      {
        field: "bronze",
        cellDataType: "number",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      minWidth: 100,
      filter: true,
      suppressHeaderMenuButton: true,
      suppressHeaderContextMenu: true,
    });
    const rowModelType = ref<RowModelType>("serverSide");
    const rowData = ref<IOlympicData[]>(null);

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

      const updateData = (data) => {
        // setup the fake server with entire dataset
        const fakeServer = new FakeServer(data);
        // create datasource with a reference to the fake server
        const datasource = getServerSideDatasource(fakeServer);
        // register the datasource with the grid
        params.api!.setGridOption("serverSideDatasource", datasource);
      };

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

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

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

[Live example: Advanced Filter](https://www.ag-grid.com/examples/server-side-model-filtering/advanced-filter/vue3)

Note that [Cell Data Types](https://www.ag-grid.com/vue-data-grid/cell-data-types/) must be supplied in order for the Advanced Filter to display the correct filter options, otherwise only `'text'` options will be displayed.

## No Matching Rows Overlay

When a filter model is applied and the data source returns no rows then the no-matching-rows overlay will automatically be displayed in the grid. See [Provided Overlays](https://www.ag-grid.com/vue-data-grid/overlays-provided/#suppress-overlays) for more details and how to suppress the overlay.
