Visualising my mapped object with Charts.js - javascript

I have a map object: As you can see it is nesting by year-month-day.
I would like to create a bar chart where you can see those numbers for "Keszeg", "Ponty"..etc based on the year-month-day.
My code is ready but i can't get it working. At this part i am getting undefinied error for the yearVal.entries.
This is the sulyhavonta.entries:
for (let [yearKey, yearVal] of sulyhavonta.entries()) {
for (let [monthKey, monthVal] of yearVal.entries())
let labels = [];
let datasets = [];
let fishData = {};
this.firebasedb.list("/fogasok/").subscribe(_data => {
// this.osszesfogasadatok = _data.filter(item => item.publikus == true);
// let fogasSzam=this.osszesfogasadatok.length;
let sulySum = _data.reduce((sum, item) => sum + parseInt(item.suly), 0);
let sulySumMap = _data.map((item, index) => {
var n = new Date(item.datum);
return {
ev: n.getFullYear(),
honap: n.getMonth() + 1,
nap: n.getDate(),
suly: item.suly,
halfaj: item.halfaj,
eteto: item.etetoanyag1,
csali: item.hasznaltcsali,
helyszin: item.helyszin
}
});
var sulySumByDate = d3.nest()
.key(function (d) {
return d.ev;
})
.key(function (d) {
return d.honap;
})
.key(function (d) {
return d.nap;
})
.key(function (d) {
return d.halfaj;
})
.rollup(function (values) {
return d3.sum(values, function (d) {
return parseInt(d.suly);
});
})
.map(sulySumMap)
var sulyhavonta=sulySumByDate;
console.log("sulyhavonta",sulyhavonta)
for (let [yearKey, yearVal] of sulyhavonta.entries()) {
for (let [monthKey, monthVal] of yearVal.entries()) {
for (let [dayKey, dayVal] of monthVal.entires()) {
labels.push(yearKey + '.' + monthKey + '.' + dayKey);
for (let [fish, fishVal] of dayVal.entires()) {
if (fishData[fish] === undefined) {
fishData[fish] = [];
}
fishData[fish].push(fishVal);
console.log("fishdata",fishData);
}
}
}
}
var colors = [
["#ce8d00", "#ffae00"],
["#007bce", "#84ceff"]
];
var i = 0;
for (let key in fishData) {
datasets.push({
label: key,
data: fishData[key],
backgroundColor: colors[i % 2][0],
hoverBackgroundColor: colors[i % 2][1],
hoverBorderWidth: 0
});
i++;
}
console.log("dataset",datasets)
});
var bar_ctx = document.getElementById('bar-chart');
var bar_chart = new Chart(bar_ctx, {
type: 'bar',
data: {
labels: labels,
datasets: datasets
},
options: {
animation: {
duration: 10,
},
scales: {
xAxes: [{
stacked: true,
gridLines: {
display: false
},
}],
yAxes: [{
stacked: true
}],
}, // scales
legend: {
display: true
}
} // options
});
Just a quick note, instead of the reading from firebase and d3 nesting, it is working with static data, but i would like to use the code above to directly read from my database.
var sulyhavonta = new Map([ [2018, new Map([ [1,new Map([[15, new
Map([['keszeg',3],['ponty',5]])], [29, new
Map([['keszeg',1],['ponty',1]])]])], [5,new Map([[24, new
Map([['keszeg',9],['ponty',7]])]])] ] )] ]);

Related

Javascript not pushing data to the dataArray

Im not a javascript guy but I had some help getting my chart working with chart js here, but since then I had to change the data structure from just 2 tables to 3 (with oneToMany - manyToOne). I feel Im pretty close but can I get some help with pushing the employeeProjectMonths to the dataArray?
The listEmployees looks like this:
var listEmployees = [
{"id":1,"name":"Bill Turner","contractedFrom":"2022-09-01","contractedTo":"2022-10-30",
"employeeProjects":[
{"id":14,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":7.7},
{"id":2,"project":{"id":6,"projectNumber":66666,"name":"Project 6","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":60.0,"remainingBookedMonths":6.0,"numberOfEmployees":6},"employeeBookedMonths":6.0},
{"id":7,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":8.0},
{"id":5,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":8.0},
{"id":15,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":8.8}]},
{"id":2,"name":"Kate Miller","contractedFrom":"2022-01-01","contractedTo":"2022-05-30",
"employeeProjects":[
{"id":3,"project":{"id":4,"projectNumber":44444,"name":"Project 4","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":40.0,"remainingBookedMonths":4.0,"numberOfEmployees":4},"employeeBookedMonths":14.0},
{"id":6,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":5.0},
{"id":8,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":5.0},
{"id":13,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":6.6}]},
{"id":3,"name":"John Smith","contractedFrom":"2022-06-01","contractedTo":"2022-12-30","employeeProjects":[
{"id":12,"project":{"id":1,"projectNumber":12345,"name":"Project 1","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":2.5}]}];
and this is the chart
const labels = listEmployees.reduce(function(result, item) {
result.push(item.name);
return result;
}, []);
const randomColorGenerator = function () {
return '#' + (Math.random().toString(16) + '0000000').slice(2, 8);
};
const projects = listEmployees.reduce(function(result, item) {
item.employeeProjects.forEach(function(prj){
const prjId = prj.project.id;
if (!result[prjId]) {
result[prjId] = {
label: prj.project.name,
data: [],
backgroundColor: randomColorGenerator()
};
}
});
return result;
}, {});
listEmployees.forEach(function(item) {
for (const prjId of Object.keys(projects)) {
const prj = projects[prjId];
const empPrj = item.employeeProjects.filter(el => el.project.id === prjId);
if (empPrj.length) {
prj.data.push(empPrj[0].employeeBookedMonths);
} else {
prj.data.push(0);
}
}
});
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: Object.values(projects)
},
options: {
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
}
});
The issue is here:
const empPrj = item.employeeProjects.filter(el => el.project.id === prjId);
because you are comparing a string with a number.
Change it in
const empPrj = item.employeeProjects.filter(el => el.project.id === parseFloat(prjId));
and it should work. See snippet.
var listEmployees = [
{"id":1,"name":"Bill Turner","contractedFrom":"2022-09-01","contractedTo":"2022-10-30",
"employeeProjects":[
{"id":14,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":7.7},
{"id":2,"project":{"id":6,"projectNumber":66666,"name":"Project 6","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":60.0,"remainingBookedMonths":6.0,"numberOfEmployees":6},"employeeBookedMonths":6.0},
{"id":7,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":8.0},
{"id":5,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":8.0},
{"id":15,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":8.8}]},
{"id":2,"name":"Kate Miller","contractedFrom":"2022-01-01","contractedTo":"2022-05-30",
"employeeProjects":[
{"id":3,"project":{"id":4,"projectNumber":44444,"name":"Project 4","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":40.0,"remainingBookedMonths":4.0,"numberOfEmployees":4},"employeeBookedMonths":14.0},
{"id":6,"project":{"id":7,"projectNumber":12345,"name":"Project 7","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":5.0},
{"id":8,"project":{"id":9,"projectNumber":56789,"name":"Project 9","startDate":"2020-10-01","endDate":"2021-12-31","projectLengthInMonths":35.0,"currentBookedMonths":30.0,"remainingBookedMonths":5.0,"numberOfEmployees":3},"employeeBookedMonths":5.0},
{"id":13,"project":{"id":8,"projectNumber":54321,"name":"Project 8","startDate":"2020-05-01","endDate":"2022-06-31","projectLengthInMonths":40.0,"currentBookedMonths":32.0,"remainingBookedMonths":8.0,"numberOfEmployees":4},"employeeBookedMonths":6.6}]},
{"id":3,"name":"John Smith","contractedFrom":"2022-06-01","contractedTo":"2022-12-30","employeeProjects":[
{"id":12,"project":{"id":1,"projectNumber":12345,"name":"Project 1","startDate":"2020-01-01","endDate":"2022-12-31","projectLengthInMonths":30.0,"currentBookedMonths":28.0,"remainingBookedMonths":2.0,"numberOfEmployees":5},"employeeBookedMonths":2.5}]}];
const labels = listEmployees.reduce(function(result, item) {
result.push(item.name);
return result;
}, []);
const randomColorGenerator = function () {
return '#' + (Math.random().toString(16) + '0000000').slice(2, 8);
};
const projects = listEmployees.reduce(function(result, item) {
item.employeeProjects.forEach(function(prj){
const prjId = prj.project.id;
if (!result[prjId]) {
result[prjId] = {
label: prj.project.name,
data: [],
backgroundColor: randomColorGenerator()
};
}
});
return result;
}, {});
listEmployees.forEach(function(item) {
for (const prjId of Object.keys(projects)) {
const prj = projects[prjId];
const empPrj = item.employeeProjects.filter(el => el.project.id === parseFloat(prjId));
if (empPrj.length) {
prj.data.push(empPrj[0].employeeBookedMonths);
} else {
prj.data.push(0);
}
}
});
const ctx = document.getElementById("myChart");
const myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: Object.values(projects)
},
options: {
scales: {
x: {
stacked: true
},
y: {
stacked: true
}
}
}
});
.myChartDiv {
max-width: 600px;
max-height: 400px;
backgroundColor: green;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.9.1/chart.min.js"></script>
<html>
<body>
<div class="myChartDiv">
<canvas id="myChart" width="600" height="400"></canvas>
</div>
</body>
</html>

How to update ChartJS in a long polling & stop animation stuttering?

I have two issues when i'm trying to update my ChartJS values / datasets, the first is when a new dataset is added to chart datasets it's placed far from other bars (this happens when there are other datasets with zero values in it) in same dataset, another issue is that the data is not updated for same dataset when it's y value is chaged.
Here is what i've tried:
let API = [{
"totpag": 6.5,
"descrpag": "CONTANTI",
"data": "2022-02-15T10:00:00"
},
{
"totpag": 5.5,
"descrpag": "POS MANUALE",
"data": "2022-02-15T10:00:00"
},
{
"totpag": 25,
"descrpag": "ASSEGNI",
"data": "2022-02-15T10:00:00"
}
]
const optionsPagamentiBar = {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: {
display: false
},
tooltip: {
mode: 'index',
intersect: 0,
usePointStyle: true,
callbacks: {
label: function(context) {
let y = context.parsed.y;
if (y) {
return context.dataset.label + ": " + "€" + context.parsed.y.toFixed(2).replace(/\d(?=(\d{3})+\.)/g, '$&,').replace(/[,.]/g, m => (m === ',' ? '.' : ','));
}
}
}
}
},
scales: {
y: {
ticks: {
display: true,
beginAtZero: true,
callback: function(value, index, values) {
return "€" + value.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ".");
}
},
grid: {
drawBorder: false,
zeroLineColor: "transparent",
}
},
x: {
display: 1,
ticks: {
padding: 10,
display: true,
fontSize: 10
},
grid: {
display: false
}
}
}
}
const chartBarPayments = new Chart(document.getElementById("chartBarPayments").getContext('2d'), {
type: 'bar',
data: {
labels: [],
datasets: [{
data: [],
}]
},
options: optionsPagamentiBar
});
let periodo = 'giorno'
function getColorsByLabels(labels) {
//const colorScale = d3.interpolateSinebow;
//const colorRangeInfo = {
// colorStart: 0.2,
// colorEnd: 1,
// useEndAsStart: true,
//};
//let COLORS = interpolateColors(labels.length, colorScale, colorRangeInfo);
let COLORS = ["rgb(167, 3, 213)", "rgb(255, 64, 64)", "rgb(24, 114, 244)", "rgb(34, 0, 97)"]
let backgroundColors = {};
COLORS.forEach((color, index) => {
backgroundColors[labels[index]] = color;
})
return backgroundColors;
}
function pagamentiPerFascia(pagamenti) {
let datasets = [];
let timePeriods = [];
let datasetLabels = [];
let indexedData = {};
pagamenti.forEach((pagamento, i) => {
let date = "";
if (periodo == "anno") {
date = moment(pagamento.data).format("MMM YYYY");
} else if (periodo == "mese") {
date = moment(pagamento.data).format("DD MMM");
} else {
date = moment(pagamento.data).format('HH:mm');
}
if (!timePeriods.includes(date)) {
timePeriods.push(date);
}
if (!datasetLabels.includes(pagamento.descrpag)) {
datasetLabels.push(pagamento.descrpag);
}
indexedData[pagamento.descrpag + date] = pagamento.totpag;
})
let backgroundColors = getColorsByLabels(datasetLabels);
datasetLabels.forEach(label => {
const dataset = {
label,
backgroundColor: backgroundColors[label],
data: [],
skipNull: true,
};
timePeriods.forEach(date => {
dataset.data.push({
x: date,
y: indexedData[label + date] || null
})
})
datasets.push(dataset);
})
updateChart(datasets)
}
function updateChart(datasets) {
chartBarPayments.data = {};
datasets.forEach((dataset) => {
// checking if dataset exists in chart
let chartdataset = chartBarPayments.data.datasets.find((data) => data.label === dataset.label);
if (chartdataset) {
dataset.data.forEach((date) => {
// checking if x value exists in chart dataset
let chartdata = chartdataset.data.find((data) => data.x === date.x);
if (chartdata) {
console.log("if", date.y)
// if x value exists i''m setting it with the new value (even if it's the same)
chartdata.y = date.y || null;
chartBarPayments.update();
} else {
// else pushing a new xy value to data
console.log("else", date.y)
chartdataset.data.push({
x: date.x,
y: date.y || null
})
chartBarPayments.update();
}
})
} else {
// if the dataset does not exists i'm pushing it as a new one
chartBarPayments.data.datasets.push(dataset);
chartBarPayments.update();
}
});
}
pagamentiPerFascia(API)
var longPolling = setInterval(() => {
API[0].totpag = 15;
API.push({
"totpag": 16.5,
"descrpag": "VISA",
"data": "2022-02-15T10:00:00"
});
API.push({
"totpag": 16.5,
"descrpag": "VISA",
"data": "2022-02-15T11:00:00"
});
pagamentiPerFascia(API)
}, 5000)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.1/moment.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js#3.7.0/dist/chart.min.js"></script>
<canvas id="chartBarPayments"></canvas>
How can i update the values and is there a way to hide zero values from the chart?
UPDATE:
Solved the issue with spacing between bars by setting null instead of 0 in empty bars and added skipNull to each dataset.
UPDATE 2:
Solved even the issue with value update by replacing
chartData = date;
with
chartData.y = date.y;
The main issue here is that i have to clear the .data every time which cause animation stuttering even when there is no new data, clearing data is needed as the dataset can change any time with all new Y labels.
I ran into a similar situation and I ended up disabling the animation, which obviously solved the problem, but because it looked a bit less dazzling the customer did not like the solution, in the end I had to utilise a hack.
Not sure if this will work for you, but in my case it did, you do this by using setTimeout to 1 millisecond.
Run the update & then set a timeout for a millisecond & run the update again. If this doesn't work, try setting arbitrary data (instead of emptying the data) & then updating to the correct dataset a millisecond later.
In my instance:
refreshScope( endscope ) {
if(this.current_scope == 'today') {
this.current_scope = `week`; // Opposite (changes data on watcher)
} else {
this.current_scope = `today`; // Opposite again.
}
setTimeout(() => {
this.current_scope = `${endscope}`;
}, 1);
}
There are of course other (better) options you can employ, as outlined by ChartJS' performance page:
https://www.chartjs.org/docs/3.1.1/general/performance.html
And ultimately disabling animation will make it seem accurate - not stutter, albeit less dazzling, and not require hacks.
Disabling animation:
new Chart(ctx, {
type: 'line',
data: data,
options: {
animation: false
}
});

undefined labels piechart - chartjs

can you help me. i want show my data in percententage value. but my label is undefined. how i show my label to?
this my chart
var options = {
tooltips: {
custom: true
},
plugins: {
datalabels: {
display: true,
formatter: (value, ctx) => {
let datasets = ctx.chart.data.datasets;
if (datasets.indexOf(ctx.dataset) === datasets.length - 1) {
let sum = datasets[0].data.reduce((a, b) => a + b, 0);
let percentage = Math.round((value / sum) * 100) + '%';
return percentage;
} else {
return percentage;
}
},
color: '#fff',
}
}
};
var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
datasets: data
},
options: options
});
Labels array is not supposed to be in the dataset itself but is supposed to be in the main data object like so:
var data = [{
data: [50, 55, 60, 33],
backgroundColor: [
"#4b77a9",
"#5f255f",
"#d21243",
"#B27200"
],
borderColor: "#fff"
}];
var options = {
plugins: {
datalabels: {
formatter: (value, ctx) => {
let sum = 0;
let dataArr = ctx.chart.data.datasets[0].data;
dataArr.map(data => {
sum += data;
});
let percentage = (value * 100 / sum).toFixed(2) + "%";
return percentage;
},
color: '#fff',
}
}
};
var ctx = document.getElementById("pie-chart").getContext('2d');
var myChart = new Chart(ctx, {
type: 'pie',
data: {
labels: ["India", "China", "US", "Canada"],
datasets: data
},
options: options
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.4/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels#0.4.0/dist/chartjs-plugin-datalabels.min.js"></script>
<canvas id="pie-chart"></canvas>

Adding color dynamically to Chart.js

I have a Chart.js project, best explained by this code below.
const response = [
{
"mmyy":"2019-12",
"promocode":"promo1",
"amount":"2776"
},
{
"mmyy":"2020-01",
"promocode":"promo1",
"amount":"1245"
},
{
"mmyy":"2020-01",
"promocode":"promo2",
"amount":"179"
}
];
var chartColors = window.chartColors;
var color = Chart.helpers.color;
var colors = [color(chartColors.red).alpha(0.5).rgbString(),
color(chartColors.orange).alpha(0.5).rgbString(),
color(chartColors.yellow).alpha(0.5).rgbString(),
color(chartColors.green).alpha(0.5).rgbString(),
color(chartColors.blue).alpha(0.5).rgbString()];
var bgColors = [];
const labels = Array.from(new Set(response.map(c => c.mmyy))).sort();
const promocodes = Array.from(new Set(response.map(c => c.promocode))).sort();
const datasets = promocodes.map(pc => ({ label: pc, data: [] }));
labels.forEach(l => {
for (let pc of promocodes) {
let city = response.find(c => c.mmyy == l && c.promocode == pc);
datasets.find(ds => ds.label == pc).data.push(city ? Number(city.amount) : 0);
}
});
var ctx = document.getElementById('promorChart').getContext('2d');
var chartColors = window.chartColors;
var color = Chart.helpers.color;
var promorChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: datasets
},
options: {
scales: {
xAxes: [{
stacked: false
}],
yAxes: [{
stacked: false,
ticks: {
// Include a dollar sign in the ticks
callback: function(value, index, values) {
return '$' + value;
}
}
}]
},
tooltips: {
callbacks: {
label: function(tooltipItems, data) {
return "$" + tooltipItems.yLabel.toString();
}
}
},
responsive: true,
elements: {
}
}
});
<canvas id="promorChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://www.chartjs.org/samples/latest/utils.js"></script>
It works great, but as you can see, it needs some color, so I am trying to add some color with this code:
const labels = Array.from(new Set(response.map(c => c.mmyy))).sort();
const promocodes = Array.from(new Set(response.map(c => c.promocode))).sort();
const datasets = promocodes.map(pc => ({ label: pc, data: [], backgroundColor: bgColors }));
labels.forEach(l => {
for (var i = 0; i < labels.count.length; i++) {
let bgColors = (colors[i % colors.length]);
};
for (let pc of promocodes) {
let city = response.find(c => c.mmyy == l && c.promocode == pc);
datasets.find(ds => ds.label == pc).data.push(city ? Number(city.amount) : 0);
}
});
But that's not working. I'm getting the error TypeError: undefined is not an object (evaluating 'labels.count.length') Could someone tell me how to add a color for each of the labels properly form the color array properly? Thanks.
In the following code snippet, I work with simple color definitions for illustrating how it can be done. Simply replace the colors array with your own colors and it should work as expected.
const response = [{
"mmyy": "2019-12",
"promocode": "promo1",
"amount": "2776"
},
{
"mmyy": "2020-01",
"promocode": "promo1",
"amount": "1245"
},
{
"mmyy": "2020-01",
"promocode": "promo2",
"amount": "179"
}
];
const colors = ['red', 'orange', 'yellow', 'green', 'blue'];
const labels = Array.from(new Set(response.map(c => c.mmyy))).sort();
const promocodes = Array.from(new Set(response.map(c => c.promocode))).sort();
let i = 0;
const datasets = promocodes.map(pc => ({
label: pc,
data: [],
backgroundColor: colors[i++]
}));
labels.forEach(l => {
for (let pc of promocodes) {
let city = response.find(c => c.mmyy == l && c.promocode == pc);
datasets.find(ds => ds.label == pc).data.push(city ? Number(city.amount) : 0);
}
});
var ctx = document.getElementById('promorChart').getContext('2d');
var chartColors = window.chartColors;
var color = Chart.helpers.color;
var promorChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: datasets
},
options: {
scales: {
xAxes: [{
stacked: false
}],
yAxes: [{
stacked: false,
ticks: {
callback: (value, index, values) => '$' + value
}
}]
},
tooltips: {
callbacks: {
label: (tooltipItems, data) => "$" + tooltipItems.yLabel.toString()
}
},
responsive: true,
elements: {}
}
});
<canvas id="promorChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
I just modified the code. You have to set up the backgroundcolor for custom bar colors.
//added for colors
function colorsFunction() {
return ['#3e95cd','#8e5ea2'];
}
const labels = Array.from(new Set(response.map(c => c.mmyy))).sort();
const promocodes = Array.from(new Set(response.map(c => c.promocode))).sort();
const datasets = promocodes.map(pc => ({ label: pc, data: [],backgroundColor: colorsFunction() })); //Modified here
add this property inside our datasets => backgroundColor: ['#3a95cd','#4e5ea2']
const response = [{
"mmyy": "2019-12",
"promocode": "promo1",
"amount": "2776"
},
{
"mmyy": "2020-01",
"promocode": "promo1",
"amount": "1245"
},
{
"mmyy": "2020-01",
"promocode": "promo2",
"amount": "179"
}
];
const labels = Array.from(new Set(response.map(c => c.mmyy))).sort();
const promocodes = Array.from(new Set(response.map(c => c.promocode))).sort();
const datasets = promocodes.map(pc => ({
label: pc,
data: [],
backgroundColor: ['#3a95cd','#4e5ea2'] // ['#3a95cd','#4e5ea2']
}));
labels.forEach(l => {
for (let pc of promocodes) {
let city = response.find(c => c.mmyy == l && c.promocode == pc);
datasets.find(ds => ds.label == pc).data.push(city ? Number(city.amount) : 0);
}
});
var ctx = document.getElementById('promorChart').getContext('2d');
var chartColors = window.chartColors;
var color = Chart.helpers.color;
var promorChart = new Chart(ctx, {
type: 'bar',
data: {
labels: labels,
datasets: datasets
},
options: {
plugins: {
colorschemes: {
scheme: 'brewer.DarkTwo3'
}
},
scales: {
xAxes: [{
stacked: false
}],
yAxes: [{
stacked: false,
ticks: {
callback: function(value, index, values) {
return '$' + value;
}
}
}]
},
tooltips: {
callbacks: {
label: function(tooltipItems, data) {
return "$" + tooltipItems.yLabel.toString();
}
}
},
responsive: true,
elements: {}
}
});
<canvas id="promorChart"></canvas>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-colorschemes"></script>

highcharts-ng ajax data load

I have the following HTTP request that i use to fill out my chart:
$scope.series = ['Moduler tager', 'Gns.score'];
$scope.activity_data = [];
$scope.activity_ticks = [];
var tmp_data = [];
$scope.bar = [];
$scope.line = [];
$http.get(api.getUrl('findSelfActivityByDivisions', null))
.success(function (response) {
response.forEach(function(y){
var i = 0;
var log_date = y.date.substr(0, y.date.indexOf('T'));
var date = new Date(log_date);
var logg_date = moment(date).fromNow();
var indexOf = tmp_data.indexOf(logg_date);
var found = false;
var index = 0;
if(tmp_data.length > 0){
tmp_data.forEach(function(current_data){
if(current_data[0] == logg_date){
found = true;
}
if(!found){
index++;
}
})
}
if(found){
var tmp = tmp_data[index];
tmp[1] = tmp[1] + y.num_modules;
tmp[2] = tmp[2] + y.num_score_modules;
tmp[3] = tmp[3] + y.sum_score;
tmp_data[index] = tmp;
}
else
{
var tmp = [logg_date, y.num_modules, y.num_score_modules, y.sum_score];
tmp_data.push(tmp);
}
})
var line = [];
var bar = [];
tmp_data.forEach(function(data){
$scope.activity_ticks.push(data[0])
line.push(data[1]);
var avg_score = data[3] / data[2];
if(isNaN(avg_score)){
avg_score = 0;
}
bar.push(avg_score);
});
$scope.line = line;
$scope.bar = bar;
});
Now then i have the following chart config:
$scope.chartConfig = {
options: {
chart: {
type: 'areaspline'
}
},
series: [{
data: $scope.bar,
type: 'column'
},{
data: $scope.line,
type: 'line'
}],
xAxis: {
categories: $scope.activity_ticks
},
title: {
text: 'Hello'
},
loading: false
}
Sadly none of the graphs are showing (im guessing it has something to do with the date comming after the load)
Can anyone help me out?
Your $scope.chartConfig is likely firing before the success callback of your $http.get(api.getUrl('findSelfActivityByDivisions', null)) completes. I am assuming $scope.chartConfig is located in a controller. Try placing a $watchGroup on the values then apply your chart rendering logic once those values resolve. An example may include
Note that $watchGroup is found within Angular as of 1.3
$scope.$watchGroup(['line', 'bar'], function(newValues, oldValues) {
// newValues[0] --> $scope.line
// newValues[1] --> $scope.bar
if(newValues !== oldValues) {
$scope.chartConfig = {
options: {
chart: {
type: 'areaspline'
}
},
series: [{
data: $scope.bar,
type: 'column'
},{
data: $scope.line,
type: 'line'
}],
xAxis: {
categories: $scope.activity_ticks
},
title: {
text: 'Hello'
},
loading: false
}
}
});

Categories

Resources