About “Chart was not disposed” warning

Are you getting a "Chart was not disposed" warning in your browser console? You're doing something wrong. Read on for an explanation.

When the warning is displayed?

When you instantiate a chart, it creates a bunch of objects as well as other stuff like event handlers. All those things occupy computer memory and consume some part of the CPU.

The chart itself also creates SVG content that it puts into a designated container - a <div> element on your web page.

It's all necessary for the operation of the chart.

Now, suppose the contents of the chart container <div> are cleared out for some reason. It could happen for a number of reasons, e.g.:

  • Container is destroyed via JavaScript because it is not needed anymore.
  • A framework like Angular or React uses its routing mechanism to switch between "pages" so currently displayed chart container gets destroyed.
  • A chart instance is replaced by another chart instance that targets the same <div> container.
  • Etc.

In all those cases, the "old" chart becomes irreparably unusable, but it still occupies memory, and it's still listening (and executing code) to events. If this happens a lot, this could lead to a serious resource leak situation.

The "Chart was not disposed" warning was introduced for specifically the reason to prevent such situations, by pro-actively informing web application developer.

How do I get rid of it?

That's easy: you need to dispose the chart instance that is not needed anymore.

We can do that by calling chart's dispose() method:

chart.dispose();
chart.dispose();

When called it will ensure that:

  • All chart's objects are properly removed from memory, by removing all references to them, allowing browser's garbage collection mechanism to effectively clear up allocated memory.
  • All event handlers (both local and document-wide) are removed.
  • All contents of the target <div> container are cleared.

Disposing previously created chart instances that are no longer needed is the only way to prevent the warning from appearing.

Vanilla JS/TS apps

If you know you are going to be overwriting or removing charts in your app, it might be a good idea to always keep a references to all chart instances you have, so that you can dispose when you need to.

Maintaining a chart "registry"

Maintaining an "registry" object that maps chart container ids to chart instances might be one way around it:

let chartReg: any = {};
function createChart(chartdiv, charttype) {
  // Check if the chart instance exists
   maybeDisposeChart(chartdiv);

  // Create new chart
   chartReg[chartdiv] = am4core.create(chartdiv, charttype);
   return chartReg[chartdiv];
}

function maybeDisposeChart(chartdiv) {
  if (chartReg[chartdiv]) {
    chartReg[chartdiv].dispose();
    delete chartReg[chartdiv];
  }
}
var chartReg = {};
function createChart(chartdiv, charttype) {
  // Check if the chart instance exists
   maybeDisposeChart(chartdiv);

  // Create new chart
   chartReg[chartdiv] = am4core.create(chartdiv, charttype);
   return chartReg[chartdiv];
}

function maybeDisposeChart(chartdiv) {
  if (chartReg[chartdiv]) {
    chartReg[chartdiv].dispose();
    delete chartReg[chartdiv];
  }
}

Finding chart instance by container reference

If you do not want to maintain your own registry, you can find chart instance by using container reference or its id.

All chart instances are logged in the global am4core.registry.baseSprites array.

All you need to do is to iterate through it and find a match:

function getChartByContainerRef(container) {
  let charts = am4core.registry.baseSprites[i];
  for(let i = 0; i < charts.length; i++) {
    if (charts[i].svgContainer === container) {
      return charts[i];
    }
  }
}

function getChartByContainerId(id) {
  let charts = am4core.registry.baseSprites[i];
  for(let i = 0; i < charts.length; i++) {
    if (charts[i].svgContainer.id == id) {
      return charts[i];
    }
  }
}
function getChartByContainerRef(container) {
  var charts = am4core.registry.baseSprites[i];
  for(var i = 0; i < charts.length; i++) {
    if (charts[i].svgContainer === container) {
      return charts[i];
    }
  }
}

function getChartByContainerId(id) {
  var charts = am4core.registry.baseSprites[i];
  for(var i = 0; i < charts.length; i++) {
    if (charts[i].svgContainer.id == id) {
      return charts[i];
    }
  }
}

React

React uses its componentWillUnmount() handler to clean up the stuff that is not needed.

Chart disposing code should go there.

MORE INFO Please refer our dedicated "Using React" article for more information and examples.

Angular

For Angular apps use its ngOnDestroy method to dispose all of the charts that need to be destroyed.

MORE INFO Please refer our dedicated "Using Angular" article for more information and examples.

Disposing external legend

If you are using an external legend, remember: it's a separate instance that needs to be disposed as well.

That means calling dispose() on both chart and the Container instance that holds your legend.

Disposing all charts at once

For this simple task, amCharts 4 comes with a built-in global function: am4core.disposeAllCharts().

am4core.disposeAllCharts();
am4core.disposeAllCharts();

Auto-disposing charts

Instead of disposing the charts with your own code, or living with the error message, you can also make amCharts 4 automatically dispose such "orphaned" charts using global option autoDispose:

am4core.options.autoDispose = true;
am4core.options.autoDispose = true;

Setting it will ensure that message is not shown, and that all overwritten charts are being automatically disposed.