---
title: "Chart State"
framework: javascript
version: "14.1.0"
---

# Chart State

The dynamic chart state can be saved, restored and updated at runtime.

## Save & Restore

#### Saving & Restoring State

```ts
import {
  AgCartesianChartOptions,
  AgCartesianSeriesTooltipRendererParams,
  AgChartState,
  AgCharts,
  AnimationModule,
  AreaSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  ModuleRegistry,
  NavigatorModule,
  NumberAxisModule,
  UnitTimeAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import { DataType, getData } from "./data";

const dateFormatter = new Intl.DateTimeFormat("en-GB");
const tooltip = {
  renderer: ({
    datum,
    yKey,
  }: AgCartesianSeriesTooltipRendererParams<DataType>) => {
    const value = `${Math.round(Number(datum[yKey]) / 100) / 10 + "k"}`;
    return { data: [{ label: dateFormatter.format(datum.date), value }] };
  },
};
let state: AgChartState = {
  version: "11.0.0",
  zoom: {
    rangeX: {
      start: {
        __type: "date",
        value: new Date("2021-01-01").getTime(),
      },
    },
  },
  legend: [
    {
      seriesId: "tate-modern",
      visible: false,
    },
    {
      seriesId: "tate-liverpool",
      visible: false,
    },
  ],
};
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  CrosshairModule,
  LegendModule,
  NavigatorModule,
  NumberAxisModule,
  UnitTimeAxisModule,
  ZoomModule,
  ContextMenuModule,
]);

const options: AgCartesianChartOptions<DataType> = {
  title: {
    text: "Total Visitors to Tate Galleries",
  },
  footnote: {
    text: "Source: Department for Digital, Culture, Media & Sport",
  },
  data: getData(),
  navigator: {
    enabled: true,
  },
  zoom: {
    enabled: true,
  },
  series: [
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Modern",
      yName: "Tate Modern",
      id: "tate-modern",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Britain",
      yName: "Tate Britain",
      id: "tate-britain",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Liverpool",
      yName: "Tate Liverpool",
      id: "tate-liverpool",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate St Ives",
      yName: "Tate St Ives",
      id: "tate-st-ives",
      tooltip,
    },
  ],
  axes: {
    x: {
      type: "unit-time",
    },
    y: {
      type: "number",
      title: {
        text: "Total visitors",
      },
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);

function saveState() {
  const newState = chart.getState();
  state = newState;
  console.log("Saved", state);
}

function restoreState() {
  chart.setState(state).then(() => {
    console.log(`Restored`, state);
  });
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).saveState = saveState;
  (<any>window).restoreState = restoreState;
}
```

[Live example: Saving & Restoring State](https://www.ag-grid.com/charts/typescript/api-state/examples/legend-state-save-restore)

Use the buttons to save and restore both the Legend and Zoom states.

```js
function saveState() {
    const newState = chart.getState();
    // save to database...
}

function restoreState() {
    // retrieve state from database...
    chart.setState(state);
}
```

In the above example:

- Zoom and pan the chart, and also toggle some legend items. Then click 'Save' to store the chart state using `chart.getState()`.
- Click the 'Restore' button to restore a saved state to the chart using `chart.setState()`.
- This will override the current state.

[Financial Charts](https://www.ag-grid.com/charts/javascript/financial-charts/) also allow save, restore and update of [annotations](https://www.ag-grid.com/charts/javascript/financial-charts-toolbar/) and [chart type](https://www.ag-grid.com/charts/javascript/financial-charts-toolbar/#chart-type-selection).

#### Saving & Restoring State

```ts
import {
  AgChartState,
  AgCharts,
  AgFinancialChartOptions,
  ContextMenuModule,
  FinancialChartModule,
  ModuleRegistry,
} from "ag-charts-enterprise";
import { getData } from "./data";

let state: AgChartState = {
  version: "11.0.0",
  chartType: "ohlc",
  annotations: [
    {
      type: "parallel-channel",
      height: 9.692307692304894,
      middle: { strokeWidth: 1, lineDash: [6, 5] },
      background: { fill: "#5090dc", fillOpacity: 0.2 },
      start: {
        x: {
          __type: "date",
          value: "Thu Mar 21 2024 18:45:00 GMT+0000 (Greenwich Mean Time)",
        },
        y: 39821.692307692305,
      },
      end: {
        x: {
          __type: "date",
          value: "Thu Mar 21 2024 18:55:00 GMT+0000 (Greenwich Mean Time)",
        },
        y: 39838.46153846154,
      },
      handle: { fill: "white" },
      stroke: "#5090dc",
      strokeOpacity: 1,
      strokeWidth: 2,
    },
  ],
  zoom: {
    rangeX: {
      start: {
        __type: "date",
        value: "Thu Mar 21 2024 18:43:00 GMT+0000 (Greenwich Mean Time)",
      },
    },
  },
};
ModuleRegistry.registerModules([FinancialChartModule]);

const options: AgFinancialChartOptions = {
  data: getData(),
  title: {
    text: "Dow Jones Industrial Average",
  },
  rangeButtons: false,
};

options.container = document.getElementById("myChart");

const chart = AgCharts.createFinancialChart(options);

function saveState() {
  const newState = chart.getState();
  state = newState;
  console.log("Saved", state);
}

function restoreState() {
  chart.setState(state).then(() => {
    console.log(`Restored`, state);
  });
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).saveState = saveState;
  (<any>window).restoreState = restoreState;
}
```

[Live example: Saving & Restoring State](https://www.ag-grid.com/charts/typescript/api-state/examples/state-save-restore)

In the above example:

- Use the toolbar to create annotations and change the chart type, and then click 'Save' to store the chart state using `chart.getState()`.
- Click the 'Restore' button to restore a saved state to the chart using `chart.setState()`.
- This will override the current state.

## Initial State

The `initialState` chart option allows creating a chart with a saved state already applied.

Additionally, mutating this option at runtime will modify the chart state dynamically.

#### Initial State

```ts
import {
  AgCartesianChartOptions,
  AgCartesianSeriesTooltipRendererParams,
  AgCharts,
  AnimationModule,
  AreaSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  ModuleRegistry,
  NavigatorModule,
  NumberAxisModule,
  UnitTimeAxisModule,
  ZoomModule,
} from "ag-charts-enterprise";
import { DataType, getData } from "./data";

const data = getData();
const dateFormatter = new Intl.DateTimeFormat("en-GB");
const tooltip = {
  renderer: ({
    datum,
    yKey,
  }: AgCartesianSeriesTooltipRendererParams<DataType>) => {
    const value = `${Math.round(Number(datum[yKey]) / 100) / 10 + "k"}`;
    return { data: [{ label: dateFormatter.format(datum.date), value }] };
  },
};
ModuleRegistry.registerModules([
  AnimationModule,
  AreaSeriesModule,
  CrosshairModule,
  LegendModule,
  NavigatorModule,
  NumberAxisModule,
  UnitTimeAxisModule,
  ZoomModule,
  ContextMenuModule,
]);

const options: AgCartesianChartOptions<DataType> = {
  title: {
    text: "Total Visitors to Tate Galleries",
  },
  footnote: {
    text: "Source: Department for Digital, Culture, Media & Sport",
  },
  data,
  navigator: {
    enabled: true,
  },
  zoom: {
    enabled: true,
  },
  initialState: {
    zoom: {
      rangeX: {
        start: {
          __type: "date",
          value: new Date("2021-01-01").getTime(),
        },
      },
    },
    legend: [
      {
        seriesId: "tate-modern",
        visible: false,
      },
    ],
  },
  series: [
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Modern",
      yName: "Tate Modern",
      id: "tate-modern",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Britain",
      yName: "Tate Britain",
      id: "tate-britain",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate Liverpool",
      yName: "Tate Liverpool",
      id: "tate-liverpool",
      tooltip,
    },
    {
      type: "area",
      xKey: "date",
      yKey: "Tate St Ives",
      yName: "Tate St Ives",
      id: "tate-st-ives",
      tooltip,
    },
  ],
  axes: {
    x: {
      type: "unit-time",
    },
    y: {
      type: "number",
      title: {
        text: "Total visitors",
      },
      label: {
        formatter: (params) => {
          return params.value / 1000 + "k";
        },
      },
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);

function showSixMonths() {
  options.initialState!.zoom = {
    rangeX: {
      start: {
        __type: "date",
        value:
          data[data.length - 1].date.getTime() - 1000 * 60 * 60 * 24 * 30 * 6,
      },
    },
  };

  chart.update(options);
}

function show2019() {
  options.initialState!.zoom = {
    rangeX: {
      start: {
        __type: "date",
        value: new Date("2019-01-01").getTime(),
      },
      end: {
        __type: "date",
        value: new Date("2020-01-01").getTime(),
      },
    },
  };

  chart.update(options);
}

function showAll() {
  options.initialState!.zoom = {};

  chart.update(options);
}

function setInitialLegendState() {
  options.initialState!.legend = [
    {
      seriesId: "tate-modern",
      visible: false,
    },
    {
      seriesId: "tate-liverpool",
      visible: false,
    },
  ];

  chart.update(options);
}

function resetInitialLegendState() {
  options.initialState!.legend = [
    {
      seriesId: "tate-modern",
      visible: true,
    },
    {
      seriesId: "tate-liverpool",
      visible: true,
    },
    {
      seriesId: "tate-britain",
      visible: true,
    },
    {
      seriesId: "tate-st-ives",
      visible: true,
    },
  ];

  chart.update(options);
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).showSixMonths = showSixMonths;
  (<any>window).show2019 = show2019;
  (<any>window).showAll = showAll;
  (<any>window).setInitialLegendState = setInitialLegendState;
  (<any>window).resetInitialLegendState = resetInitialLegendState;
}
```

[Live example: Initial State](https://www.ag-grid.com/charts/typescript/api-state/examples/initial-state)

The objects provided to this property should be the same as the object returned from the `getState()` method.

```js
{
    initialState: {
        zoom: {
            rangeX: {
                start: {
                    __type: 'date',
                    value: new Date('2021-01-01').getTime(),
                },
            },
        },
        legend: [
            {
                seriesId: 'tate-modern',
                visible: false,
            },
        ],
    },
}
```

In this example:

- The chart loads with an `initialState` for both Zoom and Legend.
- Clicking the buttons updates the `initialState`, changing the Zoom or Legend toggle state.
- Note that the same approach applies to Financial Charts.

## State Contents

- `zoom` - This object contains start and end ranges of the zoom.
- `legend` - This array contains the current visibility of each series or item in the legend.
- `legendPagination` - This number is the current legend page of a [paginated legend](https://www.ag-grid.com/charts/javascript/legend/#pagination).
- `active` - This object contains the currently active item, which is the series node or legend item that is highlighted/showing a tooltip.
- `annotations` - This object contains the position and style of any displayed drawings or text annotations.
- `collapsed` - This array contains the identifiers of the currently collapsed items in an [Org Chart](https://www.ag-grid.com/charts/javascript/org-chart/).
- `chartType` - This string is one of the [Chart Types](https://www.ag-grid.com/charts/javascript/financial-charts-configuration/#chart-types).

> **Note**
>
> [Data Selection](https://www.ag-grid.com/charts/javascript/selection/) is not part of the chart state. See [Selection API](https://www.ag-grid.com/charts/javascript/selection/#selection-api) more details.

Note that all the state properties are optional, so a property can be excluded if you do not want to restore it.

> **Note**
>
> Date objects cannot be serialised, so should instead be provided as an `AgStateSerializableDate` object in the format `{ __type: 'date', value: string | number }` with a value of any date string or a timestamp number.
>
> Dates returned from `chart.getState()` will be in the ISO-8601 format and UTC timezone.

### Zoom

Zoom state can be provided as a range or ratio on each axis direction with either the `rangeX` & `rangeY` or `ratioX` & `ratioY` properties.

If both a range and ratio are provided, only the `rangeX` and `rangeY` values will be used.

The `start` and `end` properties of `rangeX` and `rangeY` should match the [type of axis](https://www.ag-grid.com/charts/javascript/axes-types/), e.g. a date for an [Ordinal Time Axis](https://www.ag-grid.com/charts/javascript/axes-types/#time).

The `start` and `end` properties of `ratioX` and `ratioY` should be a value between `0` and `1` as a proportion of the width or height of the chart.

### Legend

The initial legend state can be configured with an array of objects defining legend items for the series in the chart. Each object includes a `seriesId` to match the series and a `visible` property to control its visibility.

For series with multiple legend items, such as `pie` or `donut`, an `itemId` specifies data elements by their index in the data array.

A `legendItemName` can be added to the legend initial state and series options, taking priority over both `seriesId` and `itemId`.

### Legend Pagination

The `legendPagination` state stores the current legend page as a zero-based index.

If the saved page does not exist due to a change in chart size or legend configuration, it is clamped to the last available page.

### Active

The `active` state gives programmatic control over chart highlighting and tooltips, as well as saving and restoring the active state.

The active item's [`itemId`](https://www.ag-grid.com/charts/javascript/events/#item-identifiers) is derived as described in the Item Identifiers section.

#### Active State

```ts
import {
  AgCartesianChartOptions,
  AgChartState,
  AgCharts,
  BarSeriesModule,
  CategoryAxisModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
} from "ag-charts-community";
import { DataType, getData } from "./data";

let state: AgChartState | undefined = undefined;
ModuleRegistry.registerModules([
  BarSeriesModule,
  LegendModule,
  NumberAxisModule,
  CategoryAxisModule,
]);

const options: AgCartesianChartOptions<DataType> = {
  data: getData(),
  title: {
    text: "Transportation Usage Over Time",
  },
  subtitle: {
    text: "Click a bar to save active (highlight/tooltip) state",
  },
  series: [
    {
      type: "bar",
      xKey: "year",
      yKey: "publicTransit",
      yName: "Public Transit",
    },
    { type: "bar", xKey: "year", yKey: "privateCar", yName: "Private Car" },
    { type: "bar", xKey: "year", yKey: "cycle", yName: "Cycle" },
    { type: "bar", xKey: "year", yKey: "other", yName: "Other" },
  ],
  listeners: {
    seriesNodeClick: () => {
      state = chart.getState();
      console.log("Saved", state);
    },
  },
  axes: {
    y: {
      type: "number",
      title: { text: "Usage (millions of trips)" },
    },
  },
  legend: {
    position: "bottom",
    toggleSeries: false,
    listeners: {
      legendItemClick: () => {
        state = chart.getState();
        console.log("Saved", state);
      },
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);

function restoreState() {
  if (state) {
    chart.setState(state).then(() => {
      console.log("Restored", state);
    });
  }
}

if (typeof window !== "undefined") {
  // Attach external event handlers to window so they can be called from index.html
  (<any>window).restoreState = restoreState;
}
```

[Live example: Active State](https://www.ag-grid.com/charts/typescript/api-state/examples/active-save-restore)

In this example:

- Click a bar or legend item to store the chart state using `chart.getState()`.
- Click the 'Restore' button to restore the saved state to the chart using `chart.setState()`.
- This will make the same item active again, showing its tooltip and highlight.

### Frozen Active

The `active.frozen` property can be used to pause user interactions.

#### Frozen Active State

```ts
import {
  AgActiveItemState,
  AgCandlestickSeriesTooltipRendererParams,
  AgCartesianChartOptions,
  AgChartInstance,
  AgChartState,
  AgCharts,
  AnimationModule,
  CandlestickSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  ModuleRegistry,
  NumberAxisModule,
  TimeAxisModule,
} from "ag-charts-enterprise";
import { TradeDatum, getData } from "./data";

let frozenChart: AgChartInstance | undefined;
function unfreeze() {
  if (frozenChart) {
    const currentState: AgChartState = frozenChart.getState();
    frozenChart.setState({
      version: currentState.version,
      active: { activeItem: currentState.active?.activeItem, frozen: false },
    });
  }
  frozenChart = undefined;
}
function tooltipRenderer({
  datum,
}: AgCandlestickSeriesTooltipRendererParams<TradeDatum>): string {
  const date = new Date(datum.date);
  const heading = date.toLocaleString("en-GB", {
    hour: "2-digit",
    minute: "2-digit",
    day: "2-digit",
    month: "short",
    year: "numeric",
  });
  const format = (v: number) => `$${v.toFixed(2)}`;
  (window as any).unfreeze = unfreeze;
  return `
        <div class="custom-tooltip">
          <span>${heading}</span>
          <div>
            <span>open</span>
            <span>${format(datum.open)}</span>
          </div>
          <div>
            <span>high</span>
            <span>${format(datum.high)}</span>
          </div>
          <div>
            <span>low</span>
            <span>${format(datum.low)}</span>
          </div>
          <div>
            <span>close</span>
            <span>${format(datum.close)}</span>
          </div>
          <div ${frozenChart ? "" : 'style="display: none"'}>
            <button type="button" onclick="window.unfreeze()">Unfreeze</button>
          </div>
        </div>`;
}
ModuleRegistry.registerModules([
  AnimationModule,
  CandlestickSeriesModule,
  ContextMenuModule,
  CrosshairModule,
  LegendModule,
  NumberAxisModule,
  TimeAxisModule,
]);

const options: AgCartesianChartOptions<TradeDatum> = {
  title: {
    text: "Ethereum Prices",
  },
  data: getData(),
  series: [
    {
      type: "candlestick",
      xKey: "date",
      openKey: "open",
      highKey: "high",
      lowKey: "low",
      closeKey: "close",
      listeners: {
        seriesNodeClick: (event) => {
          frozenChart = chart;
          const currentState: AgChartState = chart.getState();
          const activeItem: AgActiveItemState | undefined =
            currentState.active?.activeItem?.type === "series-node"
              ? {
                  type: "series-node",
                  // TODO: should event include `itemId`?
                  itemId: currentState.active.activeItem.itemId,
                  seriesId: event.seriesId,
                }
              : undefined;
          chart.setState({
            version: currentState.version,
            active: {
              frozen: true,
              activeItem,
            },
          });
        },
      },
      tooltip: {
        interaction: { enabled: true },
        position: {
          anchorTo: "chart",
          placement: "top-right",
        },
        renderer: tooltipRenderer,
      },
    },
  ],
  axes: {
    x: {
      type: "time",
    },
    y: {
      type: "number",
      label: {
        format: "$#{.2f}",
      },
    },
  },
};

options.container = document.getElementById("myChart");

const chart = AgCharts.create(options);
```

[Live example: Frozen Active State](https://www.ag-grid.com/charts/typescript/api-state/examples/frozen-active-state)

In this example:

- Clicking the chart freezes the current Active State. The Highlight & Tooltip remain static when the mouse moves.
- Clicking the 'Unfreeze' button in the Tooltip restores interactivity.

### Collapsed

The `collapsed` state stores the identifiers of items collapsed in an [Org Chart](https://www.ag-grid.com/charts/javascript/org-chart/).

Changes to this state can be listened to with the `collapsedChange` event. See the [Events API](https://www.ag-grid.com/charts/javascript/events/#collapsedchange) page for more details.

## API Reference

#### AgChartInstance

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| getState | Function |  | Returns a representation of the current state of the given `AgChartInstance`. |
| setState | Function |  | Sets the state of the given `AgChartInstance` to the state provided. |

#### InitialState

| Property | Type | Default | Description |
| --- | --- | --- | --- |
| active | AgActiveState |  | The initial picked item. |
| active.activeItem | AgActiveItemState |  | The active series datum shape. If the entire series is active, then `itemId` will be set to `undefined`. |
| active.activeItem.type (required) | 'series-node' \| 'legend' |  | Where the item activation originates from. |
| active.activeItem.seriesId (required) | string |  | The unique identifier of the series that this picked datum belongs to. |
| active.activeItem.itemId (required) | string \| number |  | The unique identifier of the picked datum. |
| active.frozen | boolean |  | The frozen state. When the picked item is frozen, user interactions with the chart will be ignored and not updated the currently picked item. |
| annotations | AgAnnotation[] |  | The initial set of annotations to display on the chart. |
| chartType | AgInitialStateChartType |  | The initial chart type. |
| collapsed | Array<string \| number> |  | The initial collapsed datums by id, for Organization Charts. |
| legend | AgInitialStateLegendOptions[] |  | The initial legend series visibility state. |
| legend.visible (required) | boolean |  | Whether the legend item is currently enabled or not. |
| legend.seriesId | string |  | Series or item id |
| legend.itemId | string |  | Legend item id - usually yKey value for cartesian series. |
| legend.legendItemName | string |  | Human-readable description of the y-values. If supplied, matching items with the same value will be toggled together. |
| legendPagination | number |  | The initial legend pagination page as a zero-based index, restored on a best-effort like-for-like basis as the page count depends on the render size. |
| zoom | AgInitialStateZoomOptions |  | The initial zoom state. |
| zoom.rangeX | AgInitialStateZoomRange |  | The initial zoom range for the x-axis. |
| zoom.rangeX.start | AgStateSerializableDate \| AgStateSerializableBigInt \| AgStateSerializableGroupingValueType \| number |  | The start value of the zoom range. A number, or a serialised value object. |
| zoom.rangeX.end | AgStateSerializableDate \| AgStateSerializableBigInt \| AgStateSerializableGroupingValueType \| number |  | The end value of the zoom range. A number, or a serialised value object. |
| zoom.rangeY | AgInitialStateZoomRange |  | The initial zoom range for the y-axis. |
| zoom.rangeY.start | AgStateSerializableDate \| AgStateSerializableBigInt \| AgStateSerializableGroupingValueType \| number |  | The start value of the zoom range. A number, or a serialised value object. |
| zoom.rangeY.end | AgStateSerializableDate \| AgStateSerializableBigInt \| AgStateSerializableGroupingValueType \| number |  | The end value of the zoom range. A number, or a serialised value object. |
| zoom.ratioX | AgInitialStateZoomRatio |  | The initial zoom ratio for the x-axis. |
| zoom.ratioX.start | Ratio |  | The start ratio of the zoom range. |
| zoom.ratioX.end | Ratio |  | The end ratio of the zoom range. |
| zoom.ratioY | AgInitialStateZoomRatio |  | The initial zoom ratio for the y-axis. |
| zoom.ratioY.start | Ratio |  | The start ratio of the zoom range. |
| zoom.ratioY.end | Ratio |  | The end ratio of the zoom range. |
| zoom.autoScaledAxes | AgAutoScaledAxes |  | Axes that are zoomed by the auto scaling functionality. |
