Justin
Justin

Reputation: 63

How to load external data in Amcharts4

I'm trying out amCharts 4 at the moment and wanted to load my json in to the graph. Because my json is nested ive added a on parseended event to change my json structure. When i console log the new data it has the correct structure. But when i want to load it into the categories, it doesn't show anything. Currently I only want the categories to show up with no extra values yet.

My component.ts

import { Component, NgZone } from '@angular/core';
import * as am4core from "@amcharts/amcharts4/core";
import * as am4charts from "@amcharts/amcharts4/charts";
import am4themes_animated from "@amcharts/amcharts4/themes/animated";

am4core.useTheme(am4themes_animated);

@Component({
  selector: 'app-chart',
  templateUrl: './chart.component.html',
  styleUrls: ['./chart.component.css']
})

export class ChartComponent {
  constructor(private zone: NgZone) { }

  ngAfterViewInit() {
    this.zone.runOutsideAngular(() => {
      let chart = am4core.create("chartdiv", am4charts.XYChart)

      chart.paddingRight = 30;
      chart.dateFormatter.inputDateFormat = "yyyy-MM-dd HH:mm";

      var colorSet = new am4core.ColorSet();
      colorSet.saturation = 0.4;
      chart.dataSource.url = "https://localhost:44321/api/upload/readFile";
      chart.dataSource.events.on("parseended", function (ev) {
        // parsed data is assigned to data source's `data` property
        var data = ev.target.data;
        var newData = [];
        data.forEach(function (dataItem) {
          var newDataItem = {};
          Object.keys(dataItem).forEach(function (key) {
            if (typeof dataItem[key] === "object") {
              newDataItem["_id"] = dataItem[key]["@id"];
            } else {
              newDataItem[key] = dataItem[key];
            }
          });
          newData.push(newDataItem);         
        });
        console.log(JSON.stringify(newData));
        return newData
      });

      var categoryAxis = chart.yAxes.push(new am4charts.CategoryAxis());
      categoryAxis.dataFields.category = "_id";
      categoryAxis.renderer.grid.template.location = 0;
      categoryAxis.renderer.inversed = true;


      var dateAxis = chart.xAxes.push(new am4charts.DateAxis());
      dateAxis.dateFormatter.dateFormat = "yyyy-MM-dd HH:mm";
      dateAxis.renderer.minGridDistance = 70;
      dateAxis.baseInterval = { count: 30, timeUnit: "minute" };
      dateAxis.max = new Date(2018, 0, 1, 24, 0, 0, 0).getTime();
      dateAxis.strictMinMax = true;
      dateAxis.renderer.tooltipLocation = 0;

      var series1 = chart.series.push(new am4charts.ColumnSeries());
      series1.columns.template.width = am4core.percent(80);
      series1.columns.template.tooltipText = "{name}: {openDateX} - {dateX}";

      series1.dataFields.openDateX = "fromDate";
      series1.dataFields.dateX = "toDate";
      series1.dataFields.categoryY = "name";
      series1.columns.template.propertyFields.fill = "color"; // get color from data
      series1.columns.template.propertyFields.stroke = "color";
      series1.columns.template.strokeOpacity = 1;

      chart.scrollbarX = new am4core.Scrollbar();

      chart.dataSource.events.on("error", function (ev) {
        console.log("Oopsy! Something went wrong");
      });
    })
  }
}

Upvotes: 1

Views: 2464

Answers (2)

notacouch
notacouch

Reputation: 3655

You have the right idea for using chart.dataSource.url for loading external data.

To parse the external JSON and format it so it is suitable for the chart, series, or category axis data, it's better to utilize adapters. Adapters allow you to tweak things to your liking. We have a guide on that here: https://www.amcharts.com/docs/v4/concepts/adapters/

In this case, once the JSON is parsed, you can use the adapter for parsedData. The code would look like this (taken and fixed from another question of yours):

chart.dataSource.adapter.add("parsedData", function(data) {
  var newData = [];
  data.forEach(function(dataItem) {
    var newDataItem = {};
    Object.keys(dataItem).forEach(function(key) {
      if (typeof dataItem[key] === "object") {
        newDataItem["_id"] = dataItem[key]["@id"];
        dataItem[key]["Column"].forEach(function(dataItem) {
          newDataItem[dataItem["@name"]] = dataItem["@id"];
        });
      } else {
        newDataItem[key] = dataItem[key];
      }
    });
    newData.push(newDataItem);
  });
  data = newData;
  return data;
});

Here's a demo (also takes sample JSON from your other question, fixes the JSON, and the formatting logic):

https://codesandbox.io/s/r1mnjq192p

Upvotes: 2

Justin
Justin

Reputation: 63

I fixed it by adding the following line: replace this: return newData with this: chart.dataSource.data = newData

Upvotes: 1

Related Questions