Search code examples
javascripthighcharts

highchart multiple chart type duplicates the series as many as the chart types


I'm trying to load multiple chart type here using Highchart.

function loadChartDataMultiViz(variables, chartTypes, chartId) {
    $.ajax({
        url: '/datacap/site/getdatamulti',
        data: { variable: variables }, // Pass comma-separated variables
        success: function(response) {
            if (Object.keys(response).length > 0) {
                var series = [];
                var categories = Object.keys(response); // Extract years for x-axis
                var titles = [];
                chartTypes = chartTypes.split(',').map(type => type.trim());
                // Create a separate series for each chart type
                chartTypes.forEach(chartType => {
                    if (chartType === 'pie') {
                        // For pie charts, format the series differently
                        series.push({
                            type: chartType,
                            name: 'Data', // Generic name for the pie chart
                            colorByPoint: true,
                            data: categories.map(year => {
                                return {
                                    name: year, // Use year or any relevant label for each slice
                                    y: response[year][Object.keys(response[year])[0]].value || 0 // Use value for each slice, default to 0 if missing
                                };
                            })
                        });

                        // Collect titles for pie chart
                        titles.push(response[categories[0]][Object.keys(response[categories[0]])[0]].title);
                    } else {
                        // For other chart types (e.g., line, bar), create a series for each variable
                        for (const variable of Object.keys(response[categories[0]])) {
                            const data = categories.map(year => {
                                return response[year][variable] ? response[year][variable].value : 0; // Default to 0 if not available
                            });

                            series.push({
                                type: chartType,
                                name: variable, // Use the variable name for the series
                                data: data,
                            });

                            // Collect titles for each variable
                            if (response[categories[0]][variable] && response[categories[0]][variable].title) {
                                titles.push(response[categories[0]][variable].title);
                            }
                        }
                    }
                });

                Highcharts.chart(chartId, {
                    chart: {
                        type: 'container' // Use a container chart to hold multiple series
                    },
                    title: {
                        text: titles.join(',<br>'), // Combine all variable titles with a comma
                        align: 'left'
                    },
                    xAxis: {
                        categories: categories,
                        title: {
                            text: 'Year' // Example label for x-axis
                        }
                    },
                    yAxis: {
                        title: {
                            text: response[categories[0]][Object.keys(response[categories[0]])[0]].unit || 'Values'
                        }
                    },
                    series: series, // Pass the constructed series (formatted for pie or other charts)
                    annotations: [],
                    plotOptions: {
                        area: {            
                            marker: {
                                enabled: false,
                                symbol: 'circle',
                                radius: 2,
                                states: {
                                    hover: {
                                        enabled: true
                                    }
                                }
                            }
                        },
                        scatter: {
                            tooltip: {
                                pointFormatter: function () {
                                    // Customize the tooltip for scatter points
                                    return 'Year: <b>' + this.category + '</b><br>' +
                                        'Value: <b>' + this.y + '</b>';
                                }
                            },
                            lineWidth: 0, // Remove any connecting lines for the scatter plot
                            marker: {
                                radius: 5 // You can adjust the marker size here
                            }
                        }
                    },
                }, function (chart) {
                    // Add annotations after the chart is created
                    const data = chart.series[0].data.map(point => point.y);
                    addAnnotations(chart, data, 'highest'); // Annotate highest value
                    addAnnotations(chart, data, 'latest');  // Annotate latest value
                });
            }
        }
    });
}

My problem is, why is the data showing up 3 times for 3 variables (if I use 3 types of chart-type) here? This shows the title and everything else (legend, tooltips) also 3 times:

loadChartDataMultiViz('4,5,8', 'area,spline,column', 'd3-chart1'); // Example for multiple series

The code shows fine if I choose only one type of chart, like this:

loadChartDataMultiViz('4,5,6', 'spline', 'd3-chart2'); // Example for multiple series 
loadChartDataMultiViz('12,8', 'area', 'd3-chart3'); // Example for multiple series

Solution

  • This is what I've come up with and it works for me:

    function loadChartDataMultiViz(variables, chartTypes, chartId) {
      $.ajax({
        url: window.location.href + "/../../featured/getdatamulti",
        data: { variable: variables }, // Pass comma-separated variables
        success: function (response) {
          if (Object.keys(response).length > 0) {
            var series = [];
            var categories = Object.keys(response); // Extract years for x-axis
            var titles = [];
            chartTypes = chartTypes.split(",").map((type) => type.trim());
            variables = variables.split(",").map((variable) => variable.trim()); // Ensure variables are treated as an array
    
            // Loop through variables and assign the correct chart type
            for (let i = 0; i < variables.length; i++) {
              const variable = variables[i];
              const chartType = chartTypes[i] || "line"; // Default to 'line' if no chartType is provided
    
              if (chartType === "pie") {
                // For pie charts, format the series differently
                series.push({
                  type: chartType,
                  name: "Data", // Generic name for the pie chart
                  colorByPoint: true,
                  data: categories.map((year) => {
                    return {
                      name: year, // Use year or any relevant label for each slice
                      y: response[year][Object.keys(response[year])[0]].value || 0, // Use value for each slice, default to 0 if missing
                    };
                  }),
                });
    
                // Collect titles for pie chart
                titles.push(
                  response[categories[0]][Object.keys(response[categories[0]])[0]]
                    .title
                );
              } else {
                // For other chart types (e.g., line, bar), create a series for each variable
                // const data = categories.map(year => {
                //     return response[year][variable] ? response[year][variable].value : 0; // Default to 0 if not available
                // });
                const data = categories.map((year) => {
                  // If the response value is null, let it stay as null
                  return response[year][Object.keys(response[year])[i]].value !== null
                    ? response[year][Object.keys(response[year])[i]].value
                    : null; // Leave as null if no value
                });
    
                series.push({
                  type: chartType,
                  name: response[categories[0]][
                    Object.keys(response[categories[0]])[i]
                  ].title,
                  // name: variable, // Use the variable name for the series
                  data: data,
                });
    
                // Collect titles for each variable
                // titles.push(response[categories[0]][Object.keys(response[categories[0]])[0]].title);
                titles.push(
                  response[categories[0]][Object.keys(response[categories[0]])[i]]
                    .title
                );
              }
            }
    
            Highcharts.chart(
              chartId,
              {
                chart: {
                  type: "container", // Use a container chart to hold multiple series
                },
                title: {
                  text: titles.join(",<br>"), // Combine all variable titles with a comma
                  align: "left",
                },
                xAxis: {
                  categories: categories,
                  title: {
                    text: "Year", // Example label for x-axis
                  },
                },
                yAxis: {
                  title: {
                    text:
                      response[categories[0]][
                        Object.keys(response[categories[0]])[0]
                      ].unit || "",
                  },
                },
                series: series, // Pass the constructed series (formatted for pie or other charts)
                annotations: [],
                plotOptions: {
                  area: {
                    marker: {
                      enabled: false,
                      symbol: "circle",
                      radius: 2,
                      states: {
                        hover: {
                          enabled: true,
                        },
                      },
                    },
                  },
                  scatter: {
                    tooltip: {
                      pointFormatter: function () {
                        // Customize the tooltip for scatter points
                        return (
                          "Year: <b>" +
                          this.category +
                          "</b><br>" +
                          "Value: <b>" +
                          this.y +
                          "</b>"
                        );
                      },
                    },
                    lineWidth: 0, // Remove any connecting lines for the scatter plot
                    marker: {
                      radius: 5, // You can adjust the marker size here
                    },
                  },
                },
              },
              function (chart) {
                // Add annotations after the chart is created
                const data = chart.series[0].data.map((point) => point.y);
                addAnnotations(chart, data, "highest"); // Annotate highest value
                addAnnotations(chart, data, "latest"); // Annotate latest value
              }
            );
          }
        },
      });
    }