---
title: "Cross Filter Chart API"
enterprise: true
framework: angular
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/angular-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-angular
    [columnDefs]="columnDefs"
    /* other grid options ... */ />

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/angular-data-grid/filter-set/) or [Multi Filter](https://www.ag-grid.com/angular-data-grid/filter-multi/). It is also important to define the [Chart Data Type](https://www.ag-grid.com/angular-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 { Component, ViewChild } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
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,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div id="wrapper">
    <div id="pieChart"></div>
    <ag-grid-angular
      id="myGrid"
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [enableCharts]="true"
      [rowData]="rowData"
      (firstDataRendered)="onFirstDataRendered($event)"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  columnDefs: ColDef[] = [
    { field: "salesRep", chartDataType: "category" },
    { field: "handset", chartDataType: "category" },
    { field: "sale", chartDataType: "series" },
    { field: "saleDate", chartDataType: "category" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    filter: "agSetColumnFilter",
    floatingFilter: true,
  };
  rowData!: any[];

  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,
    });
  }

  onGridReady(params: GridReadyEvent) {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  }
}
```

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

## Cross-filter API

The cross-filter api shares a similar api to [Range Chart](https://www.ag-grid.com/angular-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/angular-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/angular-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/angular-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/angular-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/angular-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 { Component, ViewChild } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
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,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div id="wrapper">
    <div id="columnChart"></div>
    <div id="pieChart"></div>
    <div id="barChart"></div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [enableCharts]="true"
      [chartThemeOverrides]="chartThemeOverrides"
      [rowData]="rowData"
      (firstDataRendered)="onFirstDataRendered($event)"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  columnDefs: 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",
    },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    editable: true,
    filter: "agMultiColumnFilter",
    floatingFilter: true,
  };
  chartThemeOverrides: AgChartThemeOverrides = {
    bar: {
      axes: {
        category: {
          label: {
            rotation: 0,
          },
        },
      },
    },
  };
  rowData!: any[];

  onFirstDataRendered(params: FirstDataRenderedEvent) {
    createQuarterlySalesChart(params.api);
    createSalesByRefChart(params.api);
    createHandsetSalesChart(params.api);
  }

  onGridReady(params: GridReadyEvent) {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  }
}

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,
  });
}
```

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

### Example: Sales Dashboard #2

#### Sales Dashboard 2

```ts
import { Component, ViewChild } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
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,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div id="wrapper">
    <div id="lineChart"></div>
    <div id="donutChart"></div>
    <div id="areaChart"></div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [enableCharts]="true"
      [chartThemeOverrides]="chartThemeOverrides"
      [rowData]="rowData"
      (firstDataRendered)="onFirstDataRendered($event)"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  columnDefs: 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",
    },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    editable: true,
    filter: "agMultiColumnFilter",
    floatingFilter: true,
  };
  chartThemeOverrides: AgChartThemeOverrides = {
    bar: {
      axes: {
        category: {
          label: {
            rotation: 0,
          },
        },
      },
    },
  };
  rowData!: any[];

  onFirstDataRendered(params: FirstDataRenderedEvent) {
    createQuarterlySalesChart(params.api);
    createSalesByRefChart(params.api);
    createHandsetSalesChart(params.api);
  }

  onGridReady(params: GridReadyEvent) {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  }
}

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,
  });
}
```

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

### Example: Most Populous Cities

#### Most Populous Cities

```ts
import { Component, ViewChild } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
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,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<div id="wrapper">
    <div id="barChart"></div>
    <div id="bubbleChart"></div>
    <ag-grid-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [enableCharts]="true"
      [rowData]="rowData"
      (firstDataRendered)="onFirstDataRendered($event)"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  columnDefs: ColDef[] = [
    { field: "city", chartDataType: "category" },
    { field: "country", chartDataType: "category" },
    { field: "longitude", chartDataType: "series" },
    { field: "latitude", chartDataType: "series" },
    { field: "population", chartDataType: "series" },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    editable: true,
    filter: "agMultiColumnFilter",
    floatingFilter: true,
  };
  rowData!: any[];

  onFirstDataRendered(params: FirstDataRenderedEvent) {
    createColumnChart(params.api);
    createBubbleChart(params.api);
  }

  onGridReady(params: GridReadyEvent) {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  }
}

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,
  });
}
```

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

### 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/angular-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 { Component, ViewChild } from "@angular/core";
import { AgGridAngular } from "ag-grid-angular";
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,
]);

@Component({
  selector: "my-app",
  standalone: true,
  imports: [AgGridAngular],
  template: `<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-angular
      style="width: 100%; height: 100%;"
      [columnDefs]="columnDefs"
      [defaultColDef]="defaultColDef"
      [enableCharts]="true"
      [customChartThemes]="customChartThemes"
      [chartThemes]="chartThemes"
      [chartThemeOverrides]="chartThemeOverrides"
      [rowData]="rowData"
      (firstDataRendered)="onFirstDataRendered($event)"
      (gridReady)="onGridReady($event)"
    />
  </div> `,
})
export class AppComponent {
  columnDefs: 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",
    },
  ];
  defaultColDef: ColDef = {
    flex: 1,
    editable: true,
    filter: "agMultiColumnFilter",
    floatingFilter: true,
  };
  customChartThemes: 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",
              },
            },
          },
        },
      },
    },
  };
  chartThemes: string[] = ["my-custom-theme-light", "my-custom-theme-dark"];
  chartThemeOverrides: AgChartThemeOverrides = {
    common: {
      background: {
        fill: "transparent",
      },
      zoom: {
        enabled: false,
      },
      axes: {
        number: {
          crosshair: {
            enabled: false,
          },
        },
        category: {
          crosshair: {
            enabled: false,
          },
        },
      },
    },
    bar: {
      axes: {
        category: {
          label: {
            rotation: 0,
          },
        },
      },
    },
  };
  rowData!: any[];

  onFirstDataRendered(params: FirstDataRenderedEvent) {
    createQuarterlySalesChart(params.api);
    createSalesByRefChart(params.api);
    createHandsetSalesChart(params.api);
    createBubbleChart(params.api);
  }

  onGridReady(params: GridReadyEvent) {
    getData().then((rowData) => params.api.setGridOption("rowData", rowData));
  }
}

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,
  });
}
```

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