Version: 7.0.0
Description
When an ember-highcharts component is inserted and then immediately destroyed before draw() has a chance to run: Highcharts Error #18 — fires from Highcharts' internal animation/event callbacks after the container element is removed
Root cause
onDidInsert is async. It awaits _importHighchartsDeps(), then calls drawAfterRender(), which schedules draw() via scheduleOnce('afterRender', ...).
If the component is destroyed during that async gap (or before the afterRender callback fires), willDestroy runs while this.chart is still null, so this.chart?.destroy() is a no-op. Then draw() fires from the afterRender queue, creates a real Highcharts chart instance, and assigns it to this.chart on a component that is already dead. Nothing ever calls chart.destroy(), the SVG nodes are orphaned, and when the container is torn from the DOM, any pending animation callbacks fire against a destroyed chart → Error #18.
Minimal reproduction
{{! some-parent.hbs }}
{{#if this.showChart}}
<HighCharts @content={{this.series}} @chartOptions={{this.options}} />
{{/if}}
// some-parent.js
import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
export default class SomeParent extends Component {
@tracked showChart = true;
constructor(owner, args) {
super(owner, args);
// Flip showChart off immediately after insertion — simulates a reactive
// value (e.g. an error flag in a service) being reset during navigation.
Promise.resolve().then(() => {
this.showChart = false;
});
}
}
With the reproduction above, onDidInsert begins, awaits module imports, then scheduleOnce('afterRender', this, this.draw) is registered. By the time afterRender fires, the component has been destroyed. draw() creates the chart anyway, chart.destroy() is never called, DOM nodes linger and Error #18 follows.
Suggested fix
Guard draw() against being called after the component is destroyed:
draw() {
if (this.isDestroying || this.isDestroyed) {
return;
}
const element = this.el?.querySelector('.chart-container');
// ...rest of existing logic
}
Version: 7.0.0
Description
When an ember-highcharts component is inserted and then immediately destroyed before draw() has a chance to run:
Highcharts Error #18— fires from Highcharts' internal animation/event callbacks after the container element is removedRoot cause
onDidInsert is async. It awaits _importHighchartsDeps(), then calls drawAfterRender(), which schedules draw() via scheduleOnce('afterRender', ...).
If the component is destroyed during that async gap (or before the afterRender callback fires), willDestroy runs while this.chart is still null, so this.chart?.destroy() is a no-op. Then draw() fires from the afterRender queue, creates a real Highcharts chart instance, and assigns it to this.chart on a component that is already dead. Nothing ever calls chart.destroy(), the SVG nodes are orphaned, and when the container is torn from the DOM, any pending animation callbacks fire against a destroyed chart → Error #18.
Minimal reproduction
With the reproduction above, onDidInsert begins, awaits module imports, then scheduleOnce('afterRender', this, this.draw) is registered. By the time afterRender fires, the component has been destroyed. draw() creates the chart anyway, chart.destroy() is never called, DOM nodes linger and Error #18 follows.
Suggested fix
Guard draw() against being called after the component is destroyed: