Utilizing arrays dynamically to generate data for a bar chart display in JavaScript

I'm currently working on generating a bar stack graph using the chart.js JavaScript library. My JavaScript array contains the following data:

0: {labels: "01/01/2020 00:00:00", data: 7433, category: "A"}
1: {labels: "01/01/2020 00:00:00", data: 774, category: "B"}
2: {labels: "01/01/2020 00:00:00", data: 5993, category: "C"}
3: {labels: "30/01/2020 00:00:00", data: 7624, category: "A"}
4: {labels: "30/01/2020 00:00:00", data: 900, category: "B"}
5: {labels: "30/01/2020 00:00:00", data: 5865, category: "C"}
6: {labels: "18/02/2020 00:00:00", data: 7161, category: "A"}
7: {labels: "18/02/2020 00:00:00", data: 1005, category: "B"}
8: {labels: "18/02/2020 00:00:00", data: 5940, category: "C"}

The AJAX request retrieves this data and now I need to dynamically set it in order to create a stack chart.

// STACK BAR CHART
var stackBarData = [];
var stackBarLabels = [];

$.ajax({
    type: "POST",
    async: false,
    url: "ExecView.aspx/ReturnStackBarData",
    contentType: "application/json; charset=utf-8",
    dataType: "json",
    success: function (data) {
        var stackbarDatas = data.d;
        stackBarData = new Array(stackbarDatas.length);

        console.log(stackBarData);

        for (i = 0; i < stackbarDatas.length; i++) {

            stackBarData[i] = { labels: stackbarDatas[i].label, data: stackbarDatas[i].data, category: stackbarDatas[i].category };
        }

        console.log(stackBarData); // ARRAY OUTPUT ABOVE

    }
});

var BarpopData = {
    datasets: [{
        data: stackBarData
    }],
};

I want the data array with date 01/01/20 to be shown as the first label on the X-axis, with Category A displayed at the bottom of the stack with data 7433, Category B in the middle with data 774, and Category C at the top with data 5933. This pattern should continue for the next sets of data.

I aim for a dynamic approach that adjusts automatically based on the changing data. The Y-axis should adjust its minimum and maximum values accordingly for a clear representation of the bar stack graph.

You can view an example of the expected outcome in this JS Fiddle: https://jsfiddle.net/1eq8w0Lx/. I need to replace the hardcoded values with dynamic ones from my array. How can I achieve this?

Answer №1

To begin with, organize the data to ensure they are properly arranged:

const order = ['X', 'Y', 'Z']
data.sort((x, y) => {
  const xDate = new Date(x.labels).getTime()
  const yDate = new Date(y.labels).getTime()
  if (xDate === yDate) {
    return order.indexOf(x.category) - order.indexOf(y.category)
  }
  return xDate - yDate
})

Getting the labels is straightforward:

const labels = [...new Set(data.map(item => item.labels.slice(0, -9)))]

When it comes to the datasets, its sequence should mirror that of the array order:

const datasets = order.map(o => ({ label: o, data: [] }))
for (const d of data) {
  const idx = order.indexOf(d.category)
  datasets[idx].data.push(d.data)
}

Answer №2

After reviewing the jsfiddle link provided, I made some updates to the ajax success method in order to enhance its functionality. These modifications could potentially assist you in achieving the desired outcome.

success: function (data) {
    var stackbarDatas = data.d;
    stackBarData = new Array(stackbarDatas.length);

    var dataSet = stackbarDatas.map(x=>({label: x.category, data: [x.data]}))
    var labels = stackbarDatas.map(x=>(x.label))

    var ctx = document.getElementById("myChart");
    var myChart = new Chart(ctx, {
                                   type: 'bar',
                                   data: {
                                           labels: labels ,
                                           datasets: dataSet,
                                           options: {
                                                  ...
                                                  //rest settings as it is
}

Answer №3

If you want to see a live demonstration, check it out here https://jsfiddle.net/k9j6h3tc/2/

Summary of Steps:

  1. To start, set up your chart with empty data values.
    const myChart = new Chart(document.getElementById("myChart"), {
      type: 'bar',
      data: {
        labels  : [],
        datasets: [
          {
            label          : 'A',
            data           : [],
            backgroundColor: [ ... ],
            borderColor    : [ ... ],
            borderWidth    : 2
          },
          {
            label          : 'B',
            data           : [],
            backgroundColor: [ ... ],
            borderColor    : [ ... ],
            borderWidth    : 2
          },
          {
            label          : 'C',
            data           : [],
            backgroundColor: [ ... ],
            borderColor    : [ ... ],
            borderWidth    : 2
          },
        ],
      },
      options: { ... }
    })
    
  2. The callback function for the $.ajax call should be structured like this:
    function on_success(data) {
      myChart.data.labels = [...new Set(data.map(el => el.labels.slice(0,-9)))];
      ["A", "B", "C"].forEach((cat, idx) => {
        myChart.data.datasets[idx].data,
        data.filter(el => el.category === cat).map(el => el.data)
      });
      myChart.update();
    }
    
  3. Avoid creating a new chart instance each time by using myChart.update().

Answer №4

const stackBarDataset = data.d;
        let stackBarDataArray = new Array(stackBarDataset.length);

        stackBarDataArray = stackBarDataset.map(item => ({ category: item.category, data: [item.data], backgroundColor: item.backgroundColor, borderColor: item.borderColor, borderWidth: item.borderWidth }));
        const stackBarLabels = stackBarDataset.map(item => (item.label));

        const uniqueLabels = stackBarLabels.filter((value, index, array) => array.indexOf(value) === index); 

        console.log(JSON.stringify(stackBarDataArray));

        stackBarDataArray.forEach(dataItem => {
            const categoryName = dataItem.category;
            if (!groups[dataItem.category]) {
                groups[dataItem.category] = {
                    label: dataItem.category,
                    data: [],
                    backgroundColor: [],
                    borderColor: [],
                    borderWidth: dataItem.borderWidth
                };
            }
            groups[dataItem.category].data.push(dataItem.data[0]);
            groups[dataItem.category].backgroundColor.push(dataItem.backgroundColor);
            groups[dataItem.category].borderColor.push(dataItem.borderColor);
        });

        stackBarDataArray = Object.values(groups);

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is there a way to retrieve MongoDB count results in Node.js using a callback function?

Is there a way to access mongodb count results in nodejs so that the outcome can be easily retrieved by asynchronous requests? Currently, I am able to retrieve the result and update the database successfully. However, when it comes to accessing the varia ...

Error: SyntaxError - Issue with the AJAX request

When attempting to retrieve the HTML of a page using the following ajax request: $.ajax({ type: 'GET', dataType:"jsonp", url: link, success: function(response){console.log(response)}, ...

C# - Issue with Webbrowser failing to fully load pages

I am facing an issue with loading pages completely on the web browser, likely due to heavy usage of JavaScript. To address this problem, I have integrated another browser into the project called Awesomium. I am wondering if Awesomium supports using getEle ...

endless update cycle in Vue

I'm currently working on developing a custom component. And I have an idea of how I want to use it: let app = new Vue({ el:'#app', template:` <tab> <tab-item name='1'> <h1> This is tab item 1& ...

Displaying website content within a pop-up dialog box

Currently, I am delving into the world of AJAX calls using jQuery.get() to dynamically load website content onto my HTML page. However, I have some doubts about whether I am utilizing this command correctly. As an example, I am trying to fetch data from a ...

Incorporating object into main function of VueJS root component

I have integrated VueJS into my HTML template for an application. When a button is clicked, it passes the object of a component to its root in the following manner: <button v-on:click="$root.savePlan(dataObj)"></button> The dataObj is passe ...

Unable to pass data using $.post() method

I am trying to send some data as a variable using jQuery's $.post() method to a PHP file and then display the result in a div after clicking a button. Unfortunately, I'm facing an issue where the data isn't being retrieved in the PHP file. ...

Retrieving JavaScript array data following a page reload

I am facing an issue with updating an array dynamically in my C# server-side code and then utilizing the updated data in a JQuery function on my webpage. When the page first loads, the array is filled with some default values by C#. However, when a user ma ...

Click here to navigate to the same or a different page using an anchor

I'm currently implementing this code: $(function() { $('a[href*=#]:not([href=#])').click(function() { if (location.pathname.replace(/^\//,'') == this.pathname.replace(/^\//,'') && location.hostna ...

Explaining the implementation of JQuery's onload event and its impact on reducing dependencies

Contained within a table is some data https://i.stack.imgur.com/gQyJQ.png Upon clicking the edit button, I am able to modify the information in that specific row. The Menu Category and Menu are populated through Dependent dropdowns. https://i.stack.imgur ...

Leveraging Template Variables for Styling in Vue 3's CSS Classes

Struggling to find the perfect way to utilize variables returned by Vue functions in CSS inline styles, specifically with the "width" style. I have two variables that are returned to the template and can be used with the {{}} syntax, but not directly as a ...

Using Waveskeeper for Verification: Solutions for Resolving the 'Waves is not defined' Issue

I'm currently working on creating a page that authenticates users with Waveskeeper. I have successfully installed the Waveskeeper addon on Chrome, but I keep encountering an error: ReferenceError: Waves is not defined. I've attempted to use both ...

Creating XML files using Node.js

What are some effective methods for generating XML files? Are there tools similar to the Builder in Rails, or any other recommended approaches? Appreciate any insights! ...

Do I need to make any changes to the application when adding a new couchbase node to the cluster

Currently, I am utilizing the Node.js SDK to establish a connection with a couchbase cluster. Despite this, in the Node.js documentation, there is no clear instruction on how to input multiple IP addresses (of cluster nodes) when creating the cluster objec ...

Newbie in PHP: Techniques for transferring PHP variables between different sections of PHP code

In my project, I have a file named index.php which is responsible for uploading files to the server and setting PHP variables such as $target_folder_and_file_name. This index.php file also includes the following line (originally it was in an index.html fi ...

What could be causing my Material UI Divider to appear invisible within a Material UI Container or Paper component?

Hey there! I am absolutely smitten with Material UI - it's incredibly versatile. However, I'm facing a bit of trouble with the Material UI Divider not displaying when nested within either a Container or Paper component. I've looked into it ...

Having difficulty accessing POST data through $.ajax request

I am currently working on a simple JavaScript code that is set up to send POST requests to my local server. The JavaScript and PHP files are both located on localhost, so I don't have to worry about any cross-site issues for now. Here is the JavaScrip ...

Obtaining JavaScript data using Python Selenium Web Driver

I have been attempting to execute a javascript file within a Python script using Selenium WebDriver in order to retrieve the return value from the function. Despite my efforts and research, I have not been successful after spending several hours on this ta ...

Please explain this ES6 syntax to me: Using a colon after a function call

While exploring the documentation for a flux store in React, I came across an example that caught my attention. import {ReduceStore} from 'flux/utils'; class CounterStore extends ReduceStore<number> { getInitialState(): number { ret ...

How can I pass standard HTML as a component in React?

I need help creating a Higher Order Component (HOC) that accepts a wrapper component, but allows me to pass standard HTML elements as inner content. Here is an example of what I want to achieve: type TextLike = string | {type,content} const TextLikeRender ...