(amCharts) 图表从 HTML table 获取数据。如果动态添加了新的 table 行,如何更新图例?

(amCharts) The chart gets its data from a HTML table. How to update the legend if a new table row is dynamically added?

我有一个 HTML table 作为图表的数据提供者。 table 可以通过单击按钮进行动态编辑(我可以向其中添加新行)。

我可以在每次添加新行时更新图表。然而图例保持不变,它只有三个初始图表。如何更新图表旁边的图例?

这是我的fiddle:https://jsfiddle.net/yvzj8acd/2/

这是我向 table 添加新行的 JS:

          //////////////////////////////////
          // This is where I update the chart
          //////////////////////////////////

          $(document).ready(function() {

          var newtr = "<tr class='row1a'><th>Row 4</th><td>10000</td><td>20000</td><td>5000</td><td>15000</td><td>7500</td><td>10000</td></tr>"
          var newtr2 = "<tr class='row1a'><th>Row 5</th><td>15000</td><td>30000</td><td>2000</td><td>10000</td><td>15500</td><td>7000</td></tr>"
          var newtr3 = "<tr class='row1a'><th>Row 6</th><td>1000</td><td>25000</td><td>15000</td><td>7000</td><td>10000</td><td>8000</td></tr>"

              $(".ganti").click(function(e) {
                $('#dataTable').append(newtr, newtr2, newtr3);

                generateChartData();
                chart.dataProvider = chartData;
                chart.validateData();
                chart.animateAgain();

                e.preventDefault();
              });
          });

快速参考,AmCharts.ready 相当于 $(document).ready,因此您可以轻松地将两者结合起来。

关于您的问题,您需要调整数据和图表生成方法,以便它可以处理动态添加的数据。现在,您的设置几乎被硬编码到前三行,并且永远不会添加新数据。您还需要更新图表并在添加新行时根据需要添加其他图表。

我做的第一件事是更新您的生成数据方法以动态拉取所有包含数据的行,而不是当前获取前三行的硬编码方法:

function generateChartData() {

  // initialize empty array
  chartData = [];

  // get the table
  var table = document.getElementById('dataTable');

  var years = table.rows[0].getElementsByTagName('th');

    //get the rows with graph values. Since data rows always 
  //have a class that begin with "row", use that as the query selector
  var rows = document.querySelectorAll("tr[class^='row']");

  var row;

  // iterate through the <td> elements of the first row
  // and construct chart data out of other rows as well
  for (var x = 0; x < years.length; x++) {
    //set up the initial object containing the year
    var dataElem = {
      "year": years[x].textContent
    };
    //iterate through the other rows based on the current year column (x + 1) and add that value to the
    //object
    for (row = 0; row < rows.length; row++) {
      dataElem[rows[row].cells[0].textContent] = rows[row].cells[x + 1].textContent
    }
    //append final object to chart data array
    chartData.push(dataElem);
  }
}

接下来,我创建了一个采用图表实例和 chartData 数组的 generateGraphsFromData 方法。此方法比较在 chartData 数组的第一个元素中找到的 valueFields 和图表的 graphs 数组中的 valueFields,并创建数组中没有的新图形。这适用于图表创建和更新:

//update the chart's graphs array based on the the currently known valueFields
function generateGraphsFromData(chart, chartData) {
  //get the chart graph value fields
  var graphValueFields = chart.graphs.map(function(graph) {
    return graph.valueField;
  });
  //create an array of new graph value fields by filtering out the categoryField
  //and the currently known valueFields. 
  var newGraphValueFields = Object.keys(chartData[0]).filter(function(key) {
    return key != chart.categoryField;
  }).filter(function(valueField) {
    return graphValueFields.indexOf(valueField) === -1;
  });

  //for each new value field left over, create a graph object and add to the chart.
  newGraphValueFields.forEach(function(valueField) {
    var graph = new AmCharts.AmGraph();
    graph.title = valueField;
    graph.valueField = valueField;
    graph.balloonText = "Rp[[value]]";
    graph.lineAlpha = 1;
    graph.bullet = "round";
    graph.stackable = false; // disable stacking
    chart.addGraph(graph);
  });
}

从那里我刚刚更新了你准备好的方法来调用这个函数而不是手动设置图形,同时强制隐藏前两个:

  // Create graphs
  generateGraphsFromData(chart, chartData);

  //default the other two graphs to hidden
  chart.graphs[1].hidden = true;
  chart.graphs[2].hidden = true;

然后我修改了您的点击事件以调用 generateGraphs 方法:

  $(".ganti").click(function(e) {
    $('#dataTable').append(newtr, newtr2, newtr3);

    generateChartData();
    generateGraphsFromData(chart, chartData);
    // ...

Updated fiddle。我还将 AmCharts.ready 方法移动到一个单独的独立函数中,并将其调用到 $(document).ready 中,因为无论如何两者都是相同的。如果您想将其他新图表默认为隐藏或其他任何方式,请随意调整逻辑。