---
title: "Cross Filter Chart API"
enterprise: true
framework: vue
version: "36.1.0"
---

# Cross Filter Chart API

Cross-filtering charts allow users to interact with data in an easy and intuitive way. Clicking on chart elements automatically filters values in both the grid and other cross-filter charts.

> **Warning**
>
> Cross-filtering in AG Grid is no longer being actively developed. For interactive dashboards and a more powerful cross-filtering experience, check out our purpose-built dashboarding tool [AG Studio](https://www.ag-grid.com/studio/javascript/filters/#cross-filtering).

![Cross Filtering](https://www.ag-grid.com/_astro/cross-filtering.Ced09ekD.gif)

This built-in feature of integrated charts is particularly useful for creating interactive reports and dashboards.

## Creating Cross-filter Charts

Cross-Filter charts are created programmatically using `createCrossFilterChart(params)` on the grid's API.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `createCrossFilterChart` | `Function` |  |  | Used to programmatically create cross filter charts from a range. Module: [`IntegratedChartsModule`](https://www.ag-grid.com/vue-data-grid/modules/). |

The following snippet shows how a cross-filtering pie chart can be created:

```ts
this.gridApi.createCrossFilterChart({
    chartType: 'pie',
    cellRange: {
        columns: ['salesRep', 'sale'],
    },
    aggFunc: 'sum',
});
```

Note in the snippet above that the `sale` values are aggregated by the `salesRep` category as `aggFunc: 'sum'` is specified.

A corresponding column configuration for the chart above is shown in the following snippet:

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

this.columnDefs = [
    { field: 'salesRep', filter: 'agSetColumnFilter', chartDataType: 'category' },
    { field: 'sale', chartDataType: 'series' },
];
```

> **Note**
>
> Cross-filtering Charts only support Client-Side Row Model. Grid filtering needs to be enabled on the category column(s) with either a [Set Filter](https://www.ag-grid.com/vue-data-grid/filter-set/) or [Multi Filter](https://www.ag-grid.com/vue-data-grid/filter-multi/). It is also important to define the [Chart Data Type](https://www.ag-grid.com/vue-data-grid/integrated-charts-range-chart/#coldefchartdatatype) as it's not possible to infer the type when all data is filtered out.

The following example shows how to create a simple cross-filtering pie chart. Note the following:

- **Click** on a sector of the pie chart to filter rows in the grid by the selected sales rep.
- **Ctrl (Cmd) Click** on another sector to additionally adds rows corresponding to the selected sales rep.
- **Click Chart Background** to remove / reset the filtering in the grid to restore all rows in the grid.

#### Simple Cross-Filter

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  IntegratedChartsModule,
  MultiFilterModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  RowGroupingModule,
]);

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div id="wrapper">
      <div id="pieChart"></div>
      <ag-grid-vue
        id="myGrid"
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :enableCharts="true"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "salesRep", chartDataType: "category" },
      { field: "handset", chartDataType: "category" },
      { field: "sale", chartDataType: "series" },
      { field: "saleDate", chartDataType: "category" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      filter: "agSetColumnFilter",
      floatingFilter: true,
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      params.api.createCrossFilterChart({
        chartType: "pie",
        cellRange: {
          columns: ["salesRep", "sale"],
        },
        aggFunc: "sum",
        chartThemeOverrides: {
          common: {
            title: {
              enabled: true,
              text: "Sales by Representative ($)",
            },
          },
          pie: {
            series: {
              title: {
                enabled: false,
              },
              calloutLabel: {
                enabled: false,
              },
            },
            legend: {
              position: "right",
            },
          },
        },
        sort: false,
        chartContainer: document.querySelector("#pieChart") as any,
      });
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

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

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

[Live example: Simple Cross-Filter](https://www.ag-grid.com/examples/integrated-charts-api-cross-filter-chart/simple-cross-filter/vue3)

## Cross-filter API

The cross-filter api shares a similar api to [Range Chart](https://www.ag-grid.com/vue-data-grid/integrated-charts-api-range-chart/), however there are different defaults which make sense for cross-filtering.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `createCrossFilterChart` | `Function` |  |  | Used to programmatically create cross filter charts from a range. Module: [`IntegratedChartsModule`](https://www.ag-grid.com/vue-data-grid/modules/). |

Properties available on the `CreateCrossFilterChartParams` interface.

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `chartType` | `CrossFilterChartType` | Yes |  | The type of cross-filtering chart to create. |
| `cellRange` | `ChartParamsCellRange` | Yes |  | Defines the list of columns to be charted. Note that cross-filter charts include all rows in the grid so there is no need to specify the range of rows. |
| `suppressChartRanges` | `boolean` |  | `true` | By default, when a cross-filter chart is displayed using the grid, the grid will not highlight the range the chart is charting when the chart gets focus. To show the chart range set `suppressChartRanges=false`. |
| `aggFunc` | [`string \| IAggFunc`](https://www.ag-grid.com/vue-data-grid/aggregation-custom-functions/) |  |  | The aggregation function that should be applied to all series data. The built-in aggregation functions are `'sum'`, `'min'`, `'max'`, `'count'`, `'avg'`, `'first'`, `'last'`. Alternatively, custom aggregation functions can be provided if they conform to the `IAggFunc` interface shown here. |
| `sort` | `SortModelItem[] \| boolean` |  | `true` | By default (or when `true`), the order in cross filter charts will match grid sorting. Set to `false` to disable sorting for this chart. Set to a `SortModelItem[]` to provide a custom sorting for this chart. |
| `chartThemeName` | `string` |  |  | The default theme to use for the created chart. In addition to the default options you listed, you can also provide your own [custom chart themes](https://www.ag-grid.com/vue-data-grid/integrated-charts-customisation/#custom-chart-themes). Options: `'ag-default'`, `'ag-default-dark'`, `'ag-material'`, `'ag-material-dark'`, `'ag-pastel'`, `'ag-pastel-dark'`, `'ag-vivid'`, `'ag-vivid-dark'`, `'ag-solar'`, `'ag-solar-dark'`. |
| `chartContainer` | [`HTMLElement`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement) |  |  | If the chart is to be displayed outside of the grid then a chart container should be provided. If the chart is to be displayed using the grid's popup window mechanism then leave as `undefined`. |
| `chartThemeOverrides` | [`AgChartThemeOverrides`](https://www.ag-grid.com/charts/themes-api/#reference-AgChartTheme-overrides) |  |  | Allows specific chart options in the current theme to be overridden. See [Overriding Existing Themes](https://www.ag-grid.com/vue-data-grid/integrated-charts-customisation/#overriding-themes) for more information. |
| `unlinkChart` | `boolean` |  | `false` | When enabled the chart will be unlinked from the grid after creation, any updates to the data will not be reflected in the chart. See [Unlinking Charts](https://www.ag-grid.com/vue-data-grid/integrated-charts-menu/#default-chart-menu-items) for more information. |

## Cross-filter Chart Types

The following examples show the different chart types that support cross-filtering:

### Example: Sales Dashboard #1

#### Sales Dashboard

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgChartThemeOverrides,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateEditorModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  NumberFilterModule,
  TextEditorModule,
  TextFilterModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  IntegratedChartsModule,
  MultiFilterModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  RowGroupingModule,
  NumberFilterModule,
  TextFilterModule,
  TextEditorModule,
  DateEditorModule,
  NumberEditorModule,
]);

function createQuarterlySalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "column",
    cellRange: {
      columns: ["quarter", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Quarterly Sales ($)",
        },
        legend: { enabled: false },
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
          number: {
            label: {
              formatter: (params: any) => {
                return params.value / 1000 + "k";
              },
            },
          },
        },
      },
    },
    sort: [{ colId: "quarter", sort: "asc" }],
    chartContainer: document.querySelector("#columnChart") as any,
  });
}

function createSalesByRefChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "pie",
    cellRange: {
      columns: ["salesRep", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Sales by Representative ($)",
        },
      },
      pie: {
        series: {
          title: {
            enabled: false,
          },
          calloutLabel: {
            enabled: false,
          },
        },
        legend: {
          position: "right",
        },
      },
    },
    sort: false,
    chartContainer: document.querySelector("#pieChart") as any,
  });
}

function createHandsetSalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "bar",
    cellRange: {
      columns: ["handset", "sale"],
    },
    aggFunc: "count",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Handsets Sold (Units)",
        },
        legend: { enabled: false },
      },
    },
    sort: [{ colId: "handset", sort: "asc" }],
    chartContainer: document.querySelector("#barChart") as any,
  });
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div id="wrapper">
      <div id="columnChart"></div>
      <div id="pieChart"></div>
      <div id="barChart"></div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :enableCharts="true"
        :chartThemeOverrides="chartThemeOverrides"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "salesRep", chartDataType: "category" },
      { field: "handset", chartDataType: "category" },
      {
        headerName: "Sale Price",
        field: "sale",
        maxWidth: 160,
        aggFunc: "sum",
        filter: "agNumberColumnFilter",
        chartDataType: "series",
      },
      {
        field: "saleDate",
        chartDataType: "category",
        filter: "agSetColumnFilter",
        filterParams: {
          valueFormatter: (params: ValueFormatterParams) => `${params.value}`,
        },
        sort: "asc",
      },
      {
        field: "quarter",
        maxWidth: 160,
        filter: "agSetColumnFilter",
        chartDataType: "category",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      editable: true,
      filter: "agMultiColumnFilter",
      floatingFilter: true,
    });
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      bar: {
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
        },
      },
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      createQuarterlySalesChart(params.api);
      createSalesByRefChart(params.api);
      createHandsetSalesChart(params.api);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

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

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

[Live example: Sales Dashboard](https://www.ag-grid.com/examples/integrated-charts-api-cross-filter-chart/sales-dashboard/vue3)

### Example: Sales Dashboard #2

#### Sales Dashboard 2

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgChartThemeOverrides,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  DateEditorModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  NumberFilterModule,
  TextEditorModule,
  TextFilterModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  IntegratedChartsModule,
  MultiFilterModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  RowGroupingModule,
  NumberFilterModule,
  TextFilterModule,
  NumberEditorModule,
  TextEditorModule,
  DateEditorModule,
]);

function createQuarterlySalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "line",
    cellRange: {
      columns: ["quarter", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Quarterly Sales ($)",
        },
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
          number: {
            label: {
              formatter: (params: any) => {
                return params.value / 1000 + "k";
              },
            },
          },
        },
      },
    },
    sort: [{ colId: "quarter", sort: "asc" }],
    chartContainer: document.querySelector("#lineChart") as any,
  });
}

function createSalesByRefChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "donut",
    cellRange: {
      columns: ["salesRep", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Sales by Representative ($)",
        },
      },
      pie: {
        legend: {
          position: "right",
        },
        series: {
          title: {
            enabled: false,
          },
          calloutLabel: {
            enabled: false,
          },
        },
      },
    },
    sort: false,
    chartContainer: document.querySelector("#donutChart") as any,
  });
}

function createHandsetSalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "area",
    cellRange: {
      columns: ["handset", "sale"],
    },
    aggFunc: "count",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Handsets Sold (Units)",
        },
        padding: { left: 47, right: 80 },
      },
    },
    sort: [{ colId: "handset", sort: "asc" }],
    chartContainer: document.querySelector("#areaChart") as any,
  });
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div id="wrapper">
      <div id="lineChart"></div>
      <div id="donutChart"></div>
      <div id="areaChart"></div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :enableCharts="true"
        :chartThemeOverrides="chartThemeOverrides"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "salesRep", chartDataType: "category" },
      { field: "handset", chartDataType: "category" },
      {
        headerName: "Sale Price",
        field: "sale",
        maxWidth: 160,
        aggFunc: "sum",
        filter: "agNumberColumnFilter",
        chartDataType: "series",
      },
      {
        field: "saleDate",
        chartDataType: "category",
        filter: "agSetColumnFilter",
        filterParams: {
          valueFormatter: (params: ValueFormatterParams) => `${params.value}`,
        },
        sort: "asc",
      },
      {
        field: "quarter",
        maxWidth: 160,
        filter: "agSetColumnFilter",
        chartDataType: "category",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      editable: true,
      filter: "agMultiColumnFilter",
      floatingFilter: true,
    });
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      bar: {
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
        },
      },
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      createQuarterlySalesChart(params.api);
      createSalesByRefChart(params.api);
      createHandsetSalesChart(params.api);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

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

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

[Live example: Sales Dashboard 2](https://www.ag-grid.com/examples/integrated-charts-api-cross-filter-chart/sales-dashboard2/vue3)

### Example: Most Populous Cities

#### Most Populous Cities

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  NumberFilterModule,
  TextEditorModule,
  TextFilterModule,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  IntegratedChartsModule,
  MultiFilterModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  RowGroupingModule,
  TextFilterModule,
  TextEditorModule,
  NumberFilterModule,
  NumberEditorModule,
]);

function createColumnChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "column",
    cellRange: {
      columns: ["country", "population"],
    },
    aggFunc: "count",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Number of Most Populous Cities by Country",
        },
        legend: {
          enabled: false,
        },
      },
      bar: {
        axes: {
          category: {
            label: {
              rotation: 325,
            },
          },
        },
      },
    },
    sort: [{ colId: "country", sort: "asc" }],
    chartContainer: document.querySelector("#barChart") as any,
  });
}

function createBubbleChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "bubble",
    cellRange: {
      columns: ["longitude", "latitude", "population"],
    },
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Latitude vs Longitude of Most Populous Cities",
        },
        legend: {
          enabled: false,
        },
      },
    },
    sort: false,
    chartContainer: document.querySelector("#bubbleChart") as any,
  });
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div id="wrapper">
      <div id="barChart"></div>
      <div id="bubbleChart"></div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :enableCharts="true"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "city", chartDataType: "category" },
      { field: "country", chartDataType: "category" },
      { field: "longitude", chartDataType: "series" },
      { field: "latitude", chartDataType: "series" },
      { field: "population", chartDataType: "series" },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      editable: true,
      filter: "agMultiColumnFilter",
      floatingFilter: true,
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      createColumnChart(params.api);
      createBubbleChart(params.api);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

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

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

[Live example: Most Populous Cities](https://www.ag-grid.com/examples/integrated-charts-api-cross-filter-chart/most-populous-cities/vue3)

### Example: Custom Theme

In this example, we use a custom theme to style the charts using `customChartTheme` and `chartTheme`. See the [Custom Chart Themes](https://www.ag-grid.com/vue-data-grid/integrated-charts-customisation/#custom-chart-themes) section for more information.

> **Note**
>
> Note that for cosmetic changes in cross-filtering charts, you must use a custom theme. Cross-filtering charts rely on a theme to derive filtered value colours from existing theme colours. Specifying your own colours in the theme overrides will disable this behaviour.

#### Custom Theme

```ts
import {
  createApp,
  defineComponent,
  onBeforeMount,
  ref,
  shallowRef,
} from "vue";
import { AgGridVue } from "ag-grid-vue3";
import "./style.css";
import { AgChartsEnterpriseModule } from "ag-charts-enterprise";
import {
  AgChartThemeOverrides,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  CustomChartThemes,
  DateEditorModule,
  FirstDataRenderedEvent,
  GridApi,
  GridOptions,
  GridReadyEvent,
  ModuleRegistry,
  NumberEditorModule,
  NumberFilterModule,
  TextEditorModule,
  TextFilterModule,
  ValueFormatterParams,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  IntegratedChartsModule,
  MultiFilterModule,
  RowGroupingModule,
  SetFilterModule,
} from "ag-grid-enterprise";
import { getData, phones } from "./data";
if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

ModuleRegistry.registerModules([
  ClientSideRowModelModule,
  IntegratedChartsModule.with(AgChartsEnterpriseModule),
  ColumnsToolPanelModule,
  FiltersToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  MultiFilterModule,
  SetFilterModule,
  RowGroupingModule,
  NumberFilterModule,
  TextFilterModule,
  TextEditorModule,
  DateEditorModule,
  NumberEditorModule,
]);

function createQuarterlySalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "column",
    cellRange: {
      columns: ["quarter", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Quarterly Sales ($)",
        },
        legend: { enabled: false },
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
          number: {
            label: {
              formatter: (params: any) => {
                return params.value / 1000 + "k";
              },
            },
          },
        },
      },
    },
    sort: [{ colId: "quarter", sort: "asc" }],
    chartContainer: document.querySelector("#columnChart") as any,
  });
}

function createSalesByRefChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "pie",
    cellRange: {
      columns: ["salesRep", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Sales by Representative ($)",
        },
      },
      pie: {
        series: {
          title: {
            enabled: false,
          },
          calloutLabel: {
            enabled: false,
          },
        },
        legend: {
          position: "right",
        },
      },
    },
    sort: false,
    chartContainer: document.querySelector("#pieChart") as any,
  });
}

function createHandsetSalesChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "area",
    cellRange: {
      columns: ["handset", "sale"],
    },
    aggFunc: "count",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Handsets Sold (Units)",
        },
        padding: { left: 47, right: 80 },
      },
    },
    sort: [{ colId: "handset", sort: "asc" }],
    chartContainer: document.querySelector("#areaChart") as any,
  });
}

function createBubbleChart(api: GridApi) {
  api.createCrossFilterChart({
    chartType: "bubble",
    cellRange: {
      columns: ["quarterIndex", "handsetIndex", "sale"],
    },
    aggFunc: "sum",
    chartThemeOverrides: {
      common: {
        title: {
          enabled: true,
          text: "Sales by Quarter and Handset",
        },
        legend: {
          enabled: false,
        },
        seriesArea: {
          padding: {
            left: 8,
            bottom: 8,
          },
        },
        axes: {
          number: {
            label: {
              formatter: (params: any) => {
                // For this example only: format two number series differently with a single formatter
                if (params.value < 10) {
                  if (Math.floor(params.value) !== params.value) {
                    return "";
                  }
                  return `Q${params.value}`;
                } else {
                  return phones[params.value - 10]?.handset ?? "";
                }
              },
            },
            nice: false,
          },
        },
      },
    },
    sort: false,
    chartContainer: document.querySelector("#bubbleChart") as any,
  });
}

const VueExample = defineComponent({
  template: `
        <div style="height: 100%">
                <div id="wrapper">
      <div id="charts">
        <div id="columnChart"></div>
        <div id="pieChart"></div>
        <div id="areaChart"></div>
        <div id="bubbleChart"></div>
      </div>
      <ag-grid-vue
        style="width: 100%; height: 100%;"
        @grid-ready="onGridReady"
        :columnDefs="columnDefs"
        :defaultColDef="defaultColDef"
        :enableCharts="true"
        :customChartThemes="customChartThemes"
        :chartThemes="chartThemes"
        :chartThemeOverrides="chartThemeOverrides"
        :rowData="rowData"
        @first-data-rendered="onFirstDataRendered"></ag-grid-vue>
      </div>
        </div>
    `,
  components: {
    "ag-grid-vue": AgGridVue,
  },
  setup(props) {
    const gridApi = shallowRef<GridApi | null>(null);
    const columnDefs = ref<ColDef[]>([
      { field: "salesRep", chartDataType: "category" },
      { field: "handset", chartDataType: "category" },
      { field: "handsetIndex", chartDataType: "series", hide: true },
      { field: "quarterIndex", chartDataType: "series", hide: true },
      {
        headerName: "Sale Price",
        field: "sale",
        maxWidth: 160,
        aggFunc: "sum",
        filter: "agNumberColumnFilter",
        chartDataType: "series",
      },
      {
        field: "saleDate",
        chartDataType: "category",
        filter: "agSetColumnFilter",
        filterParams: {
          valueFormatter: (params: ValueFormatterParams) => `${params.value}`,
        },
        sort: "asc",
      },
      {
        field: "quarter",
        maxWidth: 160,
        filter: "agSetColumnFilter",
        chartDataType: "category",
      },
    ]);
    const defaultColDef = ref<ColDef>({
      flex: 1,
      editable: true,
      filter: "agMultiColumnFilter",
      floatingFilter: true,
    });
    const customChartThemes = ref<CustomChartThemes>({
      "my-custom-theme-light": {
        palette: {
          fills: [
            "purple",
            "indigo",
            "blue",
            "green",
            "yellow",
            "orange",
            "red",
          ],
        },
      },
      "my-custom-theme-dark": {
        palette: {
          fills: [
            "red",
            "orange",
            "yellow",
            "green",
            "blue",
            "indigo",
            "purple",
          ],
          strokes: ["white"],
        },
        overrides: {
          common: {
            title: {
              color: "white",
            },
            axes: {
              category: {
                label: {
                  color: "white",
                },
              },
              number: {
                label: {
                  color: "white",
                },
              },
            },
            legend: {
              item: {
                label: {
                  color: "white",
                },
              },
            },
          },
        },
      },
    });
    const chartThemes = ref<string[]>([
      "my-custom-theme-light",
      "my-custom-theme-dark",
    ]);
    const chartThemeOverrides = ref<AgChartThemeOverrides>({
      common: {
        background: {
          fill: "transparent",
        },
        zoom: {
          enabled: false,
        },
        axes: {
          number: {
            crosshair: {
              enabled: false,
            },
          },
          category: {
            crosshair: {
              enabled: false,
            },
          },
        },
      },
      bar: {
        axes: {
          category: {
            label: {
              rotation: 0,
            },
          },
        },
      },
    });
    const rowData = ref<any[]>(null);

    function onFirstDataRendered(params: FirstDataRenderedEvent) {
      createQuarterlySalesChart(params.api);
      createSalesByRefChart(params.api);
      createHandsetSalesChart(params.api);
      createBubbleChart(params.api);
    }
    const onGridReady = (params: GridReadyEvent) => {
      gridApi.value = params.api;

      getData().then((rowData) => params.api.setGridOption("rowData", rowData));
    };

    return {
      gridApi,
      columnDefs,
      defaultColDef,
      customChartThemes,
      chartThemes,
      chartThemeOverrides,
      rowData,
      onGridReady,
      onFirstDataRendered,
    };
  },
});

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

[Live example: Custom Theme](https://www.ag-grid.com/examples/integrated-charts-api-cross-filter-chart/custom-theme/vue3)
