2

I am trying to achieve a drilldown functionality on an Amcharts Piechart in my angular4 project. The official wrapper has a feature to add a listener in the configuration object. This configuration object is then passed to AmChartsService to make the chart.

My problem is here:

import { AmChartsService } from "@amcharts/amcharts3-angular";

@Component({
  template: `<div id="chartdiv" [style.width.%]="100" [style.height.px]="500"></div>`
})
export class AppComponent {
  private chart: any;

  constructor(private AmCharts: AmChartsService) {}

  public whatever(){}

  ngOnInit() {
    this.chart = this.AmCharts.makeChart("chartdiv", {
      "type": "pie",
      "theme": "light",
      "dataProvider": [],
      "listeners": [{
                event: 'clickSlice',
                method: function(event) { 
                     this.whatever()<--- HERE
                }
        }],
      ...
    });
  }
}

I am not able to call a method outside the scope of the javascript function. Their tutorial shows that it is done this exact way using javascript but no indication on how to achieve it in a scenario like mine. Calling an external function is essential to change the data provider tag dynamically depending on the pieslice clicked. Note that inside the javascript function I am able to call console.log() (just not functions outside of its scope).

Below is the error that display on the browser's console:

zone.js:169 Uncaught TypeError: Cannot read property 'Call' of undefined
    at breakdown-chart.component.ts:51
    at b.a.inherits.b.fire (amcharts.js:3)
    at b.clickSlice (pie.js:10)
    at SVGGElement.<anonymous> (pie.js:5)
    at SVGGElement.wrapFn [as __zone_symbol___onmouseup] (zone.js:1199)
    at ZoneDelegate.webpackJsonp.695.ZoneDelegate.invokeTask (zone.js:398)
    at Zone.webpackJsonp.695.Zone.runTask (zone.js:165)
    at SVGGElement.ZoneTask.invoke (zone.js:460)

Thanks!

  • Yes indeed, we are trying to achieve similar things. It's weird how i wasn't able to find that post earlier. –  Jun 02 '17 at 05:14
  • It's actually one of the most common questions here about javascript (Closure functions losing the `this` binding) – Omri Luzon Jun 02 '17 at 06:18

1 Answers1

0

You can set this to a variable and then refer to it later.

import { AmChartsService } from "@amcharts/amcharts3-angular";

@Component({
  template: `<div id="chartdiv" [style.width.%]="100" [style.height.px]="500"></div>`
})
export class AppComponent {
  private chart: any;

  constructor(private AmCharts: AmChartsService) {}

  public whatever(){}

  ngOnInit() {
    // Set this to that
    let that = this;

    this.chart = this.AmCharts.makeChart("chartdiv", {
      "type": "pie",
      "theme": "light",
      "dataProvider": [],
      "listeners": [{
            event: 'clickSlice',
            method: function(event) {
                // Use that to refer to this
                that.whatever();
            }
        }],
      ...
    });
  }
}
Darlesson
  • 5,742
  • 2
  • 21
  • 26