问题
I have a HTML table that serves as the data provider for the chart. The table can be dynamically edited with a click of the button (I can add a new row to it).
I can update the chart each time a new row is added. However the legend remains the same, it only has three initial graphs. How can I update the legend alongside the chart?
Here is my fiddle: https://jsfiddle.net/yvzj8acd/2/
And here is the JS where I add new row to the table:
//////////////////////////////////
// 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();
});
});
回答1:
Quick FYI, AmCharts.ready
is equivalent to $(document).ready
, so you can easily combine the two.
As for your question, you need to tweak your data and chart generation approach so that it can handle the dynamically added data. Right now, your setup is pretty much hard-coded to the first three rows and the new data is never added. You also need to update the chart and add additional graphs as needed when new rows are added.
The first thing I did was update your generate data method to dynamically pull all rows that contain data, rather than the current hardcoded method that grabs the first three rows:
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);
}
}
Next, I created a generateGraphsFromData
method that takes the chart instance and chartData array. This method compares the valueFields found in the first element of the chartData array and the valueFields in the chart's graphs
array and creates new graphs where there aren't any in the array. This works for both chart creation and update:
//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);
});
}
From there I just updated your ready method to call this function instead of setting the graphs manually, along with forcing the first two to be hidden:
// Create graphs
generateGraphsFromData(chart, chartData);
//default the other two graphs to hidden
chart.graphs[1].hidden = true;
chart.graphs[2].hidden = true;
Then I modified your click event to call the generateGraphs method as well:
$(".ganti").click(function(e) {
$('#dataTable').append(newtr, newtr2, newtr3);
generateChartData();
generateGraphsFromData(chart, chartData);
// ...
Updated fiddle. I also moved the AmCharts.ready method into a separate standalone function and called it into $(document).ready
, since both are identical anyway. Feel free to tweak the logic if you want to default other new graphs to hidden or whatever.
来源:https://stackoverflow.com/questions/46787202/amcharts-the-chart-gets-its-data-from-a-html-table-how-to-update-the-legend-i