4
votes

I need a way in ChartJS to show multiple pieces of data inside a stacked bar chart. In the official docs the labels pertain to each segment of the stack, but I need the segments to be independent.

I have mocked up the sort of output I need to achieve. We have three stacked bars per day, each showing a separate dataset. Inside each dataset we have a segment, which is effectively a subset of that bar.

enter image description here

Unfortunately the data property inside dataset does not seem to accept an array. Is this chart possible using ChartJS?

1

1 Answers

1
votes

I'm doing this in ASP.Net/C# like this:

My data from the DB looks like this:

Size:'38 Inch' Minimum:80 Standard:85 Maximum:90

Create a model

namespace YourNameSpace.Models
{
    public class Chart
    {
        public string[] labels { get; set; }
        public List<Datasets> datasets { get; set; }
    }

    public class Datasets
    {
        public string borderColor { get; set; }
        public bool fill { get; set; }
        public string label { get; set; }
        public string backgroundColor { get; set; }
        public string type { get; set; }
        public string borderWidth { get; set; }
        public int[] data { get; set; }
    }

    public class Configurations
    {
        public string Crops { get; set; }
        public int HP { get; set; }
        public string Pump { get; set; }
        public string TractorManufacture { get; set; }
        public string TractorModel { get; set; }
    }
 }

Get your data and load up your model from your controller. I've added a 3 series for the bar chart (min,standard,max) and a line - Add the line first. The trick for loading the data is that it has to be an array of integers, for example: DataMin.ToArray().


List<string> LabelList = new List<string>();
foreach(ChartFromDB db in cdb)//ChartFromDB holds the structure mentioned above
{
    LabelList.Add(db.Size);
}

Chart _chart = new Chart();
_chart.labels = LabelList.ToArray();
_chart.datasets = new List<Datasets>();
List<Datasets> _dataSet = new List<Datasets>();

List<int> DataList = new List<int>();
List<int> DataMin = new List<int>();
List<int> DataStandard = new List<int>();
List<int> DataMax = new List<int>();

//line goes first
for (int y = 0; y < cdb.Count; y++)
{
    DataList.Add(conf.HP);
}
_dataSet.Add(new Datasets()
{
    type = "line",
    borderColor = "#FF6347",
    fill = false,
    label = "Your PTO-HP",
    data = DataList.ToArray(),
    backgroundColor = "#FF6347",
    borderWidth = "2"
});

for (int i=0;i< cdb.Count; i++)
{
    DataMax.Add(cdb[i].Maximum);
    DataStandard.Add(cdb[i].Standard);
    DataMin.Add(cdb[i].Minimum);
}

_dataSet.Add(new Datasets()
{
    type = "bar",
    fill = true,
    label = "Base - Minimum",
    data = DataMin.ToArray(),
    borderColor = "#FFE07C",
    backgroundColor = "#FFE07C",
    borderWidth = "1"
});

_dataSet.Add(new Datasets()
{
    type = "bar",
    fill = true,
    label = "Standard - Minimum",
    data = DataStandard.ToArray(),
    borderColor = "#E4A317",
    backgroundColor = "#E4A317",
    borderWidth = "1"
});

_dataSet.Add(new Datasets()
{
    type = "bar",
    fill = true,
    label = "High Performance - Minimum",
    data = DataMax.ToArray(),
    borderColor = "#AD9754",
    backgroundColor = "#AD9754",
    borderWidth = "1"
});

_chart.datasets = _dataSet;
return Json(_chart, JsonRequestBehavior.AllowGet);

On your client, make an ajax/api call to your controller and pass the return data to some function and load

function LoadCharts(data) {

        //the hi/low will allow you to dynamically adjust the upper/lower bound of the grid
        var hi = SomeMethodToGetTheUpperBoundForYourChart;
        var lo = SomeMethodToGetTheLowerBoundForYourChart;

        var ctx = document.getElementById('canvas').getContext('2d');
        var myBarChart = new Chart(ctx, {
            type: 'bar',
            data: data,
            options: {
                title: {
                    display: true,
                    text: 'Some title for your graph'
                },
                tooltips: {
                    mode: 'index',
                    intersect: false
                },
                responsive: true,
                scales: {
                    xAxes: [{
                        stacked: false
                    }],
                    yAxes: [
                        {
                            ticks: {                  
                                max: hi ,
                                min: lo,
                                stepSize: 10,
                                callback: function (value, index, values) {
                                    return value + " Some description for your value";
                                }
                            }
                        },
                        {
                        stacked: false                       
                        }, {
                            legend : {
                                display: false
                            }
                        }
                    ]
                },
                layout: {
                    padding: {
                        left: 10,
                        right: 10,
                        top: 0,
                        bottom: 0
                    }
                }
            }

        });
    }//LoadCharts

You will get something that will look like this:

ScreenShot