2

I am trying to create a bar stack graph using chart.js javascript library. I currently have an array in javascript that contains the following :

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"}

Below is the AJAX request to put the data into an array and now i need to dynamically set the data to output 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 expect all the data in the array with 01/01/20 to be my first label on the X axis and Category A to be the lowest stack with data 7433. Then I expect category B to be middle stack with data 774. Then i expect category C to be the highest stack with data 5933. The i expect another bar stack with date 30/01/2020 data.

I need this to be dynamic looking at the array as data always changes.

How can I dynamically do this - ensuring min and max Y axis is auto so is shows a good bar stack graph?

I have a JS Fiddle: https://jsfiddle.net/1eq8w0Lx/ of what i expect the outcome to look like. I need the hard coded values to be dynamic from my array. How do i achieve this output?

2
  • What if you moved your chart initialization inside the ajax request success? Commented Feb 28, 2020 at 9:05
  • Still having issues - unable to resolve Commented Mar 2, 2020 at 10:58

4 Answers 4

1
+50

First of all, sort the data to make sure they are in the correct order:

const priority = ['A', 'B', 'C']
data.sort((a, b) => {
  const aDate = new Date(a.labels).getTime()
  const bDate = new Date(b.labels).getTime()
  if (aDate === bDate) {
    return priority.indexOf(a.category) - priority.indexOf(b.category)
  }
  return aDate - bDate
})

The labels is easy to get:

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

As for the datasets, its order should be the same as the array priority:

const datasets = priority.map(p => ({ label: p, data: [] }))
for (const d of data) {
  const index = priority.indexOf(d.category)
  datasets[index].data.push(d.data)
}
Sign up to request clarification or add additional context in comments.

Comments

1

With reference to your jsfiddle link, I have modified your ajax success method logic. may this might help you to achieve the desired result

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
}

6 Comments

Still not correct but defo closer - All being stacked on to one bar. Its not separating them out on to the X axis by the date. Right now all the data is from one array and all stocked under one label. J Fiddle shows three separate outputs in the data set (one for each stacked bar)
Nope they arent
Array(9) 0: "01/01/2020 00:00:00" 1: "01/01/2020 00:00:00" 2: "01/01/2020 00:00:00" 3: "30/01/2020 00:00:00" 4: "30/01/2020 00:00:00" 5: "30/01/2020 00:00:00" 6: "18/02/2020 00:00:00" 7: "18/02/2020 00:00:00" 8: "18/02/2020 00:00:00"
Problem is here. you need to find distinct dates from this array and assign it to chart labels section
uniqueLabels = stackBarLabels.filter((v, i, a) => a.indexOf(v) === i);
|
1

You can find a working example here https://jsfiddle.net/k9j6h3tc/2/

Gist:

  1. Setup your chart. The data can be empty.
    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. $.ajax callback can look 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. Don't recreate the chart. Use myChart.update().

Comments

0
var stackbarDatas = data.d;
        stackBarData = new Array(stackbarDatas.length);

        stackBarData = stackbarDatas.map(x => ({ category: x.category, data: [x.data], backgroundColor: x.backgroundColor, borderColor: x.borderColor, borderWidth: x.borderWidth }))
        stackBarLabels = stackbarDatas.map(x => (x.label))

        uniqueLabels = stackBarLabels.filter((v, i, a) => a.indexOf(v) === i); 


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


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

        stackBarData = Object.values(groups);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.