Skip to content
Advertisement

Switching to JSON data in AmCharts not working

New user to Amcharts (and programming!) and was trying to use one of their examples (https://codepen.io/team/amcharts/pen/gOpWroQ), but when I pull the data from and external JSON file, it doesn’t work properly. The JSON structure and format is correct and I literally copied the data from the JSON file into the var data [] and it works fine.
The pen is here: https://codepen.io/moneycarlo/pen/zYKdyGz (however I can’t host a json file).

Line 10 is where I’m loading the JSON data, but if I remove the var data info and uncomment out line 10, the result doesn’t draw 4 lines. Instead, it’s 1 line with multiple stacked points on it for each date.

I’m guessing it’s something in the pre-processor. I was under the impression that when you loaded from external data like the JSON it would automatically be assigned to the data property and those functions would work the same.

What am I missing?

am4core.useTheme(am4themes_animated);

// Source data
var data = [
  {"date":"2019-07-05","domain":"aol.com","hits":"119489"},{"date":"2019-07-05","domain":"gmail.com","hits":"295834"},{"date":"2019-07-05","domain":"hotmail.com","hits":"8000"},{"date":"2019-07-05","domain":"yahoo.com","hits":"324263"},{"date":"2019-07-06","domain":"aol.com","hits":"195042"},{"date":"2019-07-06","domain":"gmail.com","hits":"258402"},{"date":"2019-07-06","domain":"hotmail.com","hits":"100000"},{"date":"2019-07-06","domain":"yahoo.com","hits":"427865"}
];

// Create chart instance
var chart = am4core.create("chartdiv", am4charts.XYChart);
//chart.dataSource.url = "data_1.php";

// Create axes
var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
dateAxis.renderer.grid.template.location = 0;
dateAxis.renderer.minGridDistance = 30;

var valueAxis = chart.yAxes.push(new am4charts.ValueAxis());

chart.colors.list = [
  am4core.color("red"),
  am4core.color("blue"),
  am4core.color("green")
];

// Create series
function createSeries(field, name, id) {
  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.valueY = "hits";
  series.dataFields.dateX = "date";
  series.name = name;
  series.tooltipText = "{dateX}: [b]{valueY}[/]";
  series.strokeWidth = 2;
  
  var bullet = series.bullets.push(new am4charts.CircleBullet());
  bullet.circle.stroke = am4core.color("#fff");
  bullet.circle.strokeWidth = 2;

  // Add data pre-processor
  series.data = data;
  series.events.on("beforedatavalidated", function(ev) {
    var source = ev.target.data;
    var data = [];
    for(var i = 0; i < source.length; i++) {
      var row = source[i];
      if (row.domain == id) {
        data.push(row);
      }
    }
    ev.target.data = data;
  });
  
  return series;
}

createSeries("hits", "Yahoo", "yahoo.com");
createSeries("hits", "Hotmail", "hotmail.com");
createSeries("hits", "Gmail", "gmail.com");

chart.legend = new am4charts.Legend();
chart.cursor = new am4charts.XYCursor();

Advertisement

Answer

dataSource assigns the data into the data array at the chart object, not at the series like the rest of your code does. You’ll need to hook into the dataSource’s parseended event and process each series with the existing beforedatavalidated code. You’ll also want to keep track of the id value in your createSeries method as it won’t be available in the parseended event:

chart.dataSource.events.on('parseended', function(ev){
  // process parsed data into each series' data array
  ev.target.component.series.each(function(series) {
    var source = ev.target.data;
    var data = [];
    for(var i = 0; i < source.length; i++) {
      var row = source[i];
      if (row.domain == series.id) {
        data.push(row);
      }
    }
    series.data = data;
  });
  // clear out data array so that it isn't re-assigned to the chart
  // data array
  ev.target.data = [];
});

// ...

function createSeries(field, name, id) {
  var series = chart.series.push(new am4charts.LineSeries());
  series.dataFields.valueY = "hits";
  series.dataFields.dateX = "date";
  series.id = id; //store id for later
  series.name = name;
  series.tooltipText = "{dateX}: [b]{valueY}[/]";
  series.strokeWidth = 2;
  
  var bullet = series.bullets.push(new am4charts.CircleBullet());
  bullet.circle.stroke = am4core.color("#fff");
  bullet.circle.strokeWidth = 2;

  return series;
}

Codepen

Advertisement