---
title: "Pivoting"
enterprise: true
framework: react
version: "36.1.0"
---

# Pivoting

Pivoting breaks down data in an additional dimension.

Pivoting can be configured in the grid column definitions or can be applied using the grid API. Users can also configure pivoting through the UI using either the [Side Bar](https://www.ag-grid.com/react-data-grid/pivoting/#using-the-side-bar) or the [Pivot Panel](https://www.ag-grid.com/react-data-grid/pivoting/#enabling-the-pivot-panel), as shown below:

#### Pivot Overview

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  PivotModule,
  RowGroupingPanelModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  PivotModule,
  FiltersToolPanelModule,
  RowGroupingPanelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "country", rowGroup: true },
    { field: "sport", pivot: true },
    { field: "year", pivot: true },
    { field: "gold", aggFunc: "sum" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 130,
      enableValue: true,
      enableRowGroup: true,
      enablePivot: true,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      minWidth: 200,
      pinned: "left",
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            autoGroupColumnDef={autoGroupColumnDef}
            pivotMode={true}
            sideBar={"columns"}
            pivotPanelShow={"always"}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Pivot Overview](https://www.ag-grid.com/examples/pivoting/pivot-overview/reactFunctionalTs)

## Enabling Pivoting

To enable pivoting, set `pivotMode: true` in the gridOptions and enable the `pivot` column property on the desired column as shown below:

```jsx
const [columnDefs, setColumnDefs] = useState([
    { field: 'country', rowGroup: true },
    { field: 'gold', aggFunc: 'sum' },
    { field: 'sport', pivot: true },
]);
const pivotMode = true;

<AgGridReact
    columnDefs={columnDefs}
    pivotMode={pivotMode}
/>
```

In the snippet above, the rows are [Grouped](https://www.ag-grid.com/react-data-grid/grouping/) on the `Country` column and [Aggregated](https://www.ag-grid.com/react-data-grid/aggregation/) to total the number of `Gold` medals won by each country. You must provide at least one aggregation column as only aggregated rows are shown when pivoting.

Pivoting is then applied to the `Sport` column values which generates a [Pivot Result Column](https://www.ag-grid.com/react-data-grid/pivoting-result-columns/) showing the total number of `Gold` medals won by each country in each sport, as seen in this example:

#### Simple Example

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  PivotModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  PivotModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "country", rowGroup: true },
    { field: "gold", aggFunc: "sum" },
    { field: "sport", pivot: true },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 130,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      minWidth: 200,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div
          style={{ display: "flex", flexDirection: "column", height: "100%" }}
        >
          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              autoGroupColumnDef={autoGroupColumnDef}
              pivotMode={true}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Simple Example](https://www.ag-grid.com/examples/pivoting/simple/reactFunctionalTs)

> **Note**
>
> Pivoting with [Tree Data](https://www.ag-grid.com/react-data-grid/tree-data/) enabled is currently not supported. Pivoting can only be used with [Row Grouping](https://www.ag-grid.com/react-data-grid/grouping/).

## Configuring via the UI

Pivoting is often controlled by end users rather than configured by developers. The grid provides some UI options for users to control these settings.

### Using the Side Bar

The [Side Bar](https://www.ag-grid.com/react-data-grid/side-bar/) is the most common control for pivoting as it allows users to toggle pivot mode (equivalent to setting the grid option `pivotMode`), as well as setting the [Row Grouped](https://www.ag-grid.com/react-data-grid/grouping/), [Aggregated](https://www.ag-grid.com/react-data-grid/aggregation/) and pivoted columns via right click context menus or drag and drop.

#### Side Bar

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  PivotModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  ClientSideRowModelModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  PivotModule,
  FiltersToolPanelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "country", rowGroup: true, enableRowGroup: true },
    { field: "gold", aggFunc: "sum", enableValue: true },
    { field: "sport", enablePivot: true },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 130,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      minWidth: 200,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div
          style={{ display: "flex", flexDirection: "column", height: "100%" }}
        >
          <div style={gridStyle}>
            <AgGridReact<IOlympicData>
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              autoGroupColumnDef={autoGroupColumnDef}
              sideBar={"columns"}
              pivotMode={true}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Side Bar](https://www.ag-grid.com/examples/pivoting/side-bar/reactFunctionalTs)

In the example above, the `Sport` column is configured with `enablePivot: true`. This enables users to pivot by the column using UI controls, for example when right clicking the column in the side bar, the option to add `Sport` to labels becomes available.

```jsx
const [columnDefs, setColumnDefs] = useState([
    // ...other column definitions
    { field: 'sport', enablePivot: true },
]);
const sideBar = 'columns';
const pivotMode = true;

<AgGridReact
    columnDefs={columnDefs}
    sideBar={sideBar}
    pivotMode={pivotMode}
/>
```

Refer to the [Column Tool Panel](https://www.ag-grid.com/react-data-grid/tool-panel-columns/) documentation for more information on configuring the [Side Bar](https://www.ag-grid.com/react-data-grid/side-bar/).

### Enabling the Pivot Panel

The pivot panel is an alternative UI control for allowing users to control pivot columns. It is a panel attached to the top of the grid similar to the [Row Group Panel](https://www.ag-grid.com/react-data-grid/grouping-group-panel/) allowing users to reorder, remove, or add pivot columns via drag and drop.

The example below demonstrates the pivot panel alongside a [Column Tool Panel](https://www.ag-grid.com/react-data-grid/tool-panel-columns/) which has been configured to increase the available space in the [Side Bar](https://www.ag-grid.com/react-data-grid/side-bar/) by hiding the pivoting section.

#### Enabling Pivot Panel

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  GridApi,
  GridOptions,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnsToolPanelModule,
  PivotModule,
  RowGroupingPanelModule,
  SideBarModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  ClientSideRowModelModule,
  PivotModule,
  SideBarModule,
  ColumnsToolPanelModule,
  RowGroupingPanelModule,
];

const GridExample = () => {
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "country", rowGroup: true, enableRowGroup: true },
    { field: "sport", pivot: true, enablePivot: true },
    { field: "year", pivot: true, enablePivot: true },
    { field: "gold", aggFunc: "sum", enableValue: true },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 130,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      minWidth: 200,
    };
  }, []);
  const sideBar = useMemo<
    SideBarDef | string | string[] | boolean | null
  >(() => {
    return {
      defaultToolPanel: "columns",
      toolPanels: [
        {
          id: "columns",
          labelDefault: "Columns",
          labelKey: "columns",
          iconKey: "columns",
          toolPanel: "agColumnsToolPanel",
          toolPanelParams: {
            suppressPivots: true,
            suppressPivotMode: true,
          },
        },
      ],
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div style={gridStyle}>
          <AgGridReact<IOlympicData>
            rowData={data}
            loading={loading}
            columnDefs={columnDefs}
            defaultColDef={defaultColDef}
            autoGroupColumnDef={autoGroupColumnDef}
            pivotMode={true}
            pivotPanelShow={"onlyWhenPivoting"}
            sideBar={sideBar}
          />
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Enabling Pivot Panel](https://www.ag-grid.com/examples/pivoting/pivot-panel/reactFunctionalTs)

This uses the following configuration to only show the pivot panel while pivoting is active:

```jsx
const [columnDefs, setColumnDefs] = useState([
    // ...other column definitions
    { field: 'sport', pivot: true, enablePivot: true },
    { field: 'year', pivot: true, enablePivot: true },
]);
const pivotMode = true;
const pivotPanelShow = 'onlyWhenPivoting';

<AgGridReact
    columnDefs={columnDefs}
    pivotMode={pivotMode}
    pivotPanelShow={pivotPanelShow}
/>
```

### Pivot Panel in the Toolbar

The Pivot Panel can be embedded in the [Quick Access Toolbar](https://www.ag-grid.com/react-data-grid/toolbar/#row-group-and-pivot-panels) using the `agPivotPanelToolbarItem` built-in item, configured independently of `pivotPanelShow`.

```jsx
const toolbar = {
    items: ['agPivotPanelToolbarItem'],
};

<AgGridReact toolbar={toolbar} />
```

## Pivot Mode vs Pivot Active

It is possible to have pivot mode turned on even though there is no pivot active, on the grid. A pivot is active when one or more of the pivot columns is used as a column label. In this scenario, the grid will display the data as normal but will strip out columns that have no grouping or value active.

The example below demonstrates the difference between pivot mode and having a column with pivot active. The example has three modes of operation that can be switched between using the top buttons. The modes are as follows:

- **1 - Grouping Active:** This is normal grouping. The grid groups with aggregations over Gold, Silver and Bronze. The user can drill down to the lowest level row data and columns without aggregation or group (eg Country, Year, Date and Sport) are shown.
- **2 - Grouping Active with Pivot Mode:** This is grouping with `pivotMode=true`, but without any pivot active. The data shown is identical to the first option except the grid removes access to the lowest level row data and columns without aggregation or group are not shown.
- **3 - Grouping Active with Pivot Mode and Pivot Active:** This is grouping with pivotMode=true and pivot active. Note that the Year column has been added to the Column Labels and there are now pivot result columns for each year.

#### Pivot Mode Vs Pivot Active

```tsx
"use client";

import React, {
  useCallback,
  useMemo,
  useRef,
  useState,
  StrictMode,
} from "react";
import { createRoot } from "react-dom/client";
import { AgGridReact, AgGridProvider } from "ag-grid-react";
import "./styles.css";
import {
  AutoGroupColumnDef,
  ClientSideRowModelModule,
  ColDef,
  ColGroupDef,
  ColumnApiModule,
  GridApi,
  GridOptions,
  ModuleRegistry,
  SideBarDef,
  enableDevValidations,
} from "ag-grid-community";
import {
  ColumnMenuModule,
  ColumnsToolPanelModule,
  ContextMenuModule,
  FiltersToolPanelModule,
  PivotModule,
  RowGroupingPanelModule,
} from "ag-grid-enterprise";
import { IOlympicData } from "./interfaces";
import { useFetchJson } from "./useFetchJson";

if (process.env.NODE_ENV !== "production") {
  enableDevValidations();
}

const modules = [
  ClientSideRowModelModule,
  ColumnApiModule,
  ColumnsToolPanelModule,
  ColumnMenuModule,
  ContextMenuModule,
  PivotModule,
  FiltersToolPanelModule,
  RowGroupingPanelModule,
];

const GridExample = () => {
  const gridRef = useRef<AgGridReact<IOlympicData>>(null);
  const containerStyle = useMemo(() => ({ width: "100%", height: "100%" }), []);
  const gridStyle = useMemo(() => ({ height: "100%", width: "100%" }), []);

  const [columnDefs, setColumnDefs] = useState<ColDef[]>([
    { field: "country", rowGroup: true, enableRowGroup: true },
    { field: "year", rowGroup: true, enableRowGroup: true, enablePivot: true },
    { field: "date" },
    { field: "sport" },
    { field: "gold", aggFunc: "sum" },
    { field: "silver", aggFunc: "sum" },
    { field: "bronze", aggFunc: "sum" },
  ]);
  const defaultColDef = useMemo<ColDef>(() => {
    return {
      flex: 1,
      minWidth: 150,
    };
  }, []);
  const autoGroupColumnDef = useMemo<AutoGroupColumnDef>(() => {
    return {
      minWidth: 250,
    };
  }, []);

  const { data, loading } = useFetchJson<IOlympicData>(
    "https://www.ag-grid.com/example-assets/olympic-winners.json",
  );

  const onBtNormal = useCallback(() => {
    gridRef.current!.api.setGridOption("pivotMode", false);
    gridRef.current!.api.applyColumnState({
      state: [
        { colId: "country", rowGroup: true },
        { colId: "year", rowGroup: true },
      ],
      defaultState: {
        pivot: false,
        rowGroup: false,
      },
    });
  }, []);

  const onBtPivotMode = useCallback(() => {
    gridRef.current!.api.setGridOption("pivotMode", true);
    gridRef.current!.api.applyColumnState({
      state: [
        { colId: "country", rowGroup: true },
        { colId: "year", rowGroup: true },
      ],
      defaultState: {
        pivot: false,
        rowGroup: false,
      },
    });
  }, []);

  const onBtFullPivot = useCallback(() => {
    gridRef.current!.api.setGridOption("pivotMode", true);
    gridRef.current!.api.applyColumnState({
      state: [
        { colId: "country", rowGroup: true },
        { colId: "year", pivot: true },
      ],
      defaultState: {
        pivot: false,
        rowGroup: false,
      },
    });
  }, []);

  return (
    <AgGridProvider modules={modules}>
      <div style={containerStyle}>
        <div className="example-wrapper">
          <div style={{ marginBottom: "5px" }}>
            <button onClick={onBtNormal}>1 - Grouping Active</button>
            <button onClick={onBtPivotMode}>
              2 - Grouping Active with Pivot Mode
            </button>
            <button onClick={onBtFullPivot}>
              3 - Grouping Active with Pivot Mode and Pivot Active
            </button>
          </div>

          <div style={gridStyle} className="ag-theme-quartz">
            <AgGridReact<IOlympicData>
              ref={gridRef}
              rowData={data}
              loading={loading}
              columnDefs={columnDefs}
              defaultColDef={defaultColDef}
              autoGroupColumnDef={autoGroupColumnDef}
              sideBar={"columns"}
            />
          </div>
        </div>
      </div>
    </AgGridProvider>
  );
};

const root = createRoot(document.getElementById("root")!);
root.render(
  <StrictMode>
    <GridExample />
  </StrictMode>,
);
```

[Live example: Pivot Mode Vs Pivot Active](https://www.ag-grid.com/examples/pivoting/pivot-mode/reactFunctionalTs)

Note that a pivot can only be active if pivot mode is on. If pivot mode is off, all pivot columns are ignored.

## API Reference

> **Note**
>
> The pivot state can be saved and restored as part of [Grid State](https://www.ag-grid.com/react-data-grid/grid-state/).

Pivoting can be controlled using the following grid API methods:

| Property | Type | Required | Default | Description |
| --- | --- | --- | --- | --- |
| `isPivotMode` | `Function` |  |  | Returns whether pivot mode is currently active. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `getPivotColumns` | `Function` |  |  | Get the columns which the grid is pivoting on. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `setPivotColumns` | `Function` |  |  | Set the columns for the grid to pivot on. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `addPivotColumns` | `Function` |  |  | Add columns for the grid to pivot on. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `removePivotColumns` | `Function` |  |  | Stops the grid from pivoting on the provided columns. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `getPivotResultColumn` | `Function` |  |  | Returns the pivot result column for the given `pivotKeys` and `valueColId`. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `setPivotResultColumns` | `Function` |  |  | Set explicit pivot column definitions yourself. Used for advanced use cases only. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |
| `getPivotResultColumns` | `Function` |  |  | Returns the grid's pivot result columns. Module: [`PivotModule`](https://www.ag-grid.com/react-data-grid/modules/). |

## See Also

- [Editing Groups](https://www.ag-grid.com/react-data-grid/grouping-edit/) for editing pivot aggregated values with cascading updates to children
