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
              }
            );
          }
        },
      });
    }