# Updating charts

> Every chart function returns a handle. Use it to draw new data, change options, stop a chart from following its container, and clean up when it goes away.

`lineChart()`, `barChart()`, `pieChart()` and `chart()` draw the chart right away and return a handle. Keep it: it's how you give the chart new data, and how you tell it you're done with it.

| Method            | What it does                                                                       |
| ----------------- | ---------------------------------------------------------------------------------- |
| `update(changes)` | Merges the changes into the config and draws the chart again                       |
| `detach()`        | Stops following the container's size; the chart stays as it is                     |
| `destroy()`       | Detaches, removes the SVG and removes every listener                               |
| `on()`, `off()`   | Adds and removes listeners, see [Events and plugins](https://chartist.dev/docs/events-and-plugins/)       |
| `setOptions()`    | Presets only: changes the options and draws again, see [new options](#new-options) |

## New data

Pass `update()` the parts of the config that changed. Press **Edit** and then the button:

**New data** (runs in the browser):

`src/main.ts`:

```ts
import 'chartist/styles.css';
import { barChart } from 'chartist';

const labels = ['Q1', 'Q2', 'Q3', 'Q4'];
const random = () => labels.map(() => Math.round(Math.random() * 9) + 1);

const chart = barChart('#chart', {
  labels,
  series: [
    [5, 4, 3, 7],
    [3, 2, 9, 5]
  ]
});

document.querySelector('#shuffle')?.addEventListener('click', () => {
  chart.update({ data: { labels, series: [random(), random()] } });
});
```

`index.html`:

```html
<!doctype html>
<html>
  <head>
    <meta charset="UTF-8" />
    <script type="module" src="/src/main.ts"></script>
  </head>
  <body>
    <div id="chart" class="ct-golden-section"></div>
    <button id="shuffle" type="button">New numbers</button>
  </body>
</html>
```

The merge is shallow: each key you pass replaces that key, the rest stays. `update({ data })` replaces all of the data, labels included, so pass the whole data object, not only the series that changed. The same goes for `axes` and `layers` in a `chart()` config.

```ts
import { autoScaleAxis, cartesianAxes, chart, line, stepAxis } from 'chartist';

const labels = ['Mon', 'Tue', 'Wed'];
const handle = chart('#chart', {
  data: { labels, series: [[1, 3, 2]] },
  axes: cartesianAxes([
    { id: 'x', side: 'bottom', type: stepAxis() },
    { id: 'y', side: 'left', type: autoScaleAxis() }
  ]),
  layers: [line()]
});

// New data; the axes and layers stay.
handle.update({ data: { labels, series: [[2, 4, 3]] } });

// Another look; the data stays.
handle.update({ layers: [line({ showArea: true, showPoint: false })] });
```

Every update runs the whole pipeline again, and your plugins and listeners stay. They aren't part of what `update()` takes: add and remove listeners with `on()` and `off()`.

Each render draws a new SVG and replaces the old one. That's why [CSS animations](https://chartist.dev/docs/animations/) play again after an update: the elements are new.

## New options

`update()` takes the config of `chart()`, so on a preset chart it replaces the `data`, but options like `showArea` or `stackBars` aren't part of it. The presets' handles have `setOptions()` for those. The options you pass extend the current ones; with `{ replace: true }` they start from the defaults instead, and the options you gave before are gone:

```ts
import { lineChart } from 'chartist';

const chart = lineChart(
  '#chart',
  { series: [[1, 3, 2, 5]] },
  { showPoint: false }
);

// Areas too; showPoint: false stays.
chart.setOptions({ showArea: true });

// From the defaults: points again, and areas.
chart.setOptions({ showArea: true }, { replace: true });
```

[Responsive options](https://chartist.dev/docs/responsive/) still apply on top, and new data from `update({ data })` stays when they change. `plugins` and `on` are set at creation.

## Redrawing on resize

You don't need to listen to `resize` on the window. A chart watches its container with a `ResizeObserver` and lays itself out again when the container's size changes, whether the window, a sidebar or a CSS grid changed it. Only the layout and later phases run again; the config and data are reused.

Two things make this work: the container needs a size, and the chart needs room to follow it. [Sizing charts](https://chartist.dev/docs/sizing-charts/) covers both. For different options at different sizes, see [Responsive sugar topping](https://chartist.dev/docs/responsive/).

Charts with [SVG labels](https://chartist.dev/docs/server-rendering/#svg-or-html-labels) also lay out again when web fonts finish loading, since Chartist may have measured the labels before the font arrived.

## Detach and destroy

`detach()` stops a chart from following its container (and, for presets, the media queries of their responsive options). The SVG and your listeners stay, and `update()` still draws. Use it to freeze a chart, for example before printing or while you animate its container.

`destroy()` is for when the chart goes away: it detaches, removes the SVG from the container and removes every listener. Calling it twice is safe. In a component framework, destroy the chart where the component cleans up, so no observer keeps a removed element alive:

```ts
import { lineChart, type ChartHandle } from 'chartist';

let handle: ChartHandle | undefined;

export function mount(element: HTMLElement) {
  handle = lineChart(element, { series: [[1, 3, 2]] });
}

export function unmount() {
  handle?.destroy();
  handle = undefined;
}
```

In the API reference: [the chart handle](https://chartist.dev/api/chart/#ChartHandle).

Next: [animate charts with CSS](https://chartist.dev/docs/animations/), or [write a plugin](https://chartist.dev/docs/events-and-plugins/).
