I am developing a small dashboard in ASP.NET
, with the help of , C#
and am having a problem generating a stacked horizontal bar chart using Chart.js .
I have the data of some technicians who were assigned a certain number of tickets, which according to the image correspond to the axis Y
of the graph. A
, B
, C
and D
represent each technician and datasets from 1 to 4 represent the status of each ticket. What I want to obtain in the graph is the number of tickets that each technician has, taking into account his status. I attach an example image of what I want to do:
Mistake:
I am making the expected horizontal bar graph as indicated in the previous example, but I have not been able to see the datasets and their colors correctly.
What I have achieved so far is to see the technicians with the number of tickets that each one has, but the dataset that represents the status at the bottom of the graph is repeated, in addition to ASIGNADO
having other statuses and each dataset , that is, each state, it has to be represented by a color:
To be more exact here I add the example Stacked bar
that is found in the documentation ofChart.js
The data is structured as follows in the table from where I am extracting the information that I want to show, where TK_HD_TICKETS_ID
are the tickets that are registered and from where I want to obtain the quantity, in TK_CT_STATUS_ID
which the status of the ticket is stored and in TK_BT_EMPLOYEES_ID
which is the technician who do you have that ticket
The following is the function Javascript
with which I am going to load the data in the graph:
function loadEmployeesChart() {
document.getElementById("chart-employee").remove();
let auxCanvasEmployee = document.createElement('canvas');
auxCanvasEmployee.setAttribute('id', 'chart-employee');
auxCanvasEmployee.setAttribute('style', 'width: 720px; height: 600px');
document
.querySelector('#chartEmployeeContainer')
.appendChild(auxCanvasEmployee);
var canvas = document.getElementById("chart-employee");
var ctx = canvas.getContext("2d");
var dataEmployee;
var myNewChart;
$.ajax({
url: document.getElementById("employeeChart").value,
type: "POST",
dataType: "json",
data: {
refreshType: document.getElementById("dataOption").value
},
success: function (data) {
var dataChart = [];
var label = [];
var datalabels = [];
var stacks = []
for (let idx in data.DashboardTicketList) {
if (data.DashboardTicketList.hasOwnProperty(idx)) {
dataChart.push(data.DashboardTicketList[idx].TicketsCount);
label.push(data.DashboardTicketList[idx].TicketsAsignedTo);
datalabels.push(data.DashboardTicketList[idx].TicketsClasificationType);
}
}
var count = false;
for (let idx in dataChart) {
if (dataChart[idx] > 0) {
count = true;
break;
}
}
if (count) {
document.getElementById('noDataEmployee').style.display = 'none';
} else {
document.getElementById('noDataEmployee').style.display = 'block';
}
dataEmployee = {
labels: label,
datasets: [{
label: datalabels,
data: dataChart,
}],
};
myNewChart = new Chart(ctx, {
type: 'horizontalBar',
data: dataEmployee,
options: {
maintainAspectRatio: false,
scales: {
xAxes: [{
stacked: true // this should be set to make the bars stacked
}],
yAxes: [{
stacked: true // this also..
}]
},
legend: {
position: 'bottom',
padding: 5,
labels:
{
pointStyle: 'circle',
usePointStyle: true
}
}
},
});
},
error: function () { }
});
}
The problem you have is in the transformation you make of the data that comes to you from the query and in the implementation of the same. You are practically creating as many
labels
ordatasets
as results you get from the query, and you should do this by grouping the results, otherwise you will have a lot of duplicate data. The best thing is that your data has already been grouped from the server, but taking as a source the data that arrives at this moment, I will try to describe a possible solution step by step (although there are many possible ones).Imagine that the query returns a number
x
of rows, let's take the following for this example:First of all, the
labels
ones needed by the graph must be created (these must be unique, there must be no repeated elements):This should return the following array:
Then you need to filter your data to group them, for this you can generate an object made up of type properties
TicketsClasificationType
and as the value of said properties, an object made up of type propertiesTicketsAsignedTo
and valuesTicketsCount
:This will return an object like the following:
By having the query data already grouped, the array
datasets
you need could be generated:Here is an example snippet so you can see the code working:
In this fiddle there is an example adapted from this SO question , which you can use as a base.
If you look at
datasets
, each element of the same group repeatsdata
. The difference is that it changes thestack
, which would be the subgroup. If you put the original data, more detail could be given on how to prepare thedatasets
.