Add data dynamically to chart - javascript
In my code I'm getting an array of inputs arrayinput[] and an array of numbers arraynumber[] from my local storage. The length of the arrays can vary, but it's always arrayinput.length = arraynumber.length.
Now I want to create a horizontal bar chart with these arrays as data.
So arrayinput is on the y axis and arraynumbers on the x axis. But my problem is I don't know how to do that, because the arrays can have any length.
Is it possible to add the arrays to the chart dynamically?
Here I made an example of what I'm trying to do.
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal" ></canvas>
</div>
let arrayinput = ["apple", "banana", "pineapple", "cherry","peach"] ;
let arraynumber = ["5", "10", "3", "8", "1"];
var number=[];
for(var i=0;i<arrayinput.length;i++){
number[i] = parseInt(arraynumber[i]);
}
new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: ["apple", "banana", "pineapple", "cherry","peach"],
datasets: [
{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
//here I want the elements of number
data: [5,10,3,8,1]
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
Yes it is possible, although you are using a verry outdated version of the lib you might want to consider updating it
V2:
const chart = new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: [],
datasets: [{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
//here I want the elements of number
data: []
}]
},
options: {
legend: {
display: false
},
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
const addFruits = () => {
chart.data.labels = ["apple", "banana", "pineapple", "cherry", "peach"];
chart.data.datasets[0].data = [5, 10, 3, 8, 1];
chart.update();
}
addFruits()
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
V3:
const chart = new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'bar',
data: {
//here I want all elements of arrayinut
labels: [],
datasets: [{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2", "#3cba9f", "#e8c3b9", "#c45850"],
//here I want the elements of number
data: []
}]
},
options: {
indexAxis: 'y',
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'Fruits'
},
},
scales: {
y: {
beginAtZero: false
}
},
}
});
const addFruits = () => {
chart.data.labels = ["apple", "banana", "pineapple", "cherry", "peach"];
chart.data.datasets[0].data = [5, 10, 3, 8, 1];
chart.update();
}
addFruits()
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.5.0/chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
You can directly use arrayinput inside the function, same for arraynumber.
HTML:
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.min.js"></script>
<div class="chartcontainer">
<canvas id="bar-chart-horizontal"></canvas>
</div>
Javascript:
var arrayinput = ["apple", "banana", "pineapple", "cherry","peach"] ;
var arraynumber = ["5", "10", "3", "8", "1"];
var number=[];
for(var i=0;i<arrayinput.length;i++){
number[i] = parseInt(arraynumber[i]);
}
new Chart(document.getElementById("bar-chart-horizontal"), {
type: 'horizontalBar',
data: {
//here I want all elements of arrayinut
labels: arrayinput,
datasets: [
{
label: "Number of fruits",
//here I need to create arrayinput.length differnt colors but thats not that important now
backgroundColor: ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"],
//here I want the elements of number
data: arraynumber
}
]
},
options: {
legend: { display: false },
title: {
display: true,
text: 'Fruits'
},
scales: {
xAxes: [{
ticks: {
beginAtZero: true
}
}]
},
}
});
For using different colors for the chart, you can roughly estimate the maximum number of entries in arrayinput and generate the color array of that size. For example: If you know that entries in the arrayinput will never exceed 1000, you can make an array of 1000 colors, and can make a new array of out of this as per your requirement.
Like this:
var backgroundColor = ["#3e95cd", "#8e5ea2","#3cba9f","#e8c3b9","#c45850"];
var colorArray = [];
//Max value of arrayinput is say 5
for(var i=0; i<arrayinput.length; i++) {
colorArray.push(backgroundColor[i]);
}
Use this colorArray in the function directly same like arrayinput.
Live Demo Here: https://codepen.io/Hitesh_Vadher/pen/vYZmdMZ
Related
how to display last x float number value in chartjs
I'm making a Vertical Bar Chart using react-chartjs-2. and I have array of lots of float numbers stored. I tried to use chartjs callback option to display only the last value on a graph. But the value in the callback is an integer, so I can't take the value I want. for example, const xAsisData = [ 1.11, 4.23, 7.34, ... , 403.78 ] // includes hundreds scales: { x: { ticks: { autoSkip: false, callback: (value) => { // if value === last ? value : null // ! but last value is 309, not 403.78 }, }, Is there any other option I can use?
You get the index and ticks array as well in your callback so you can just check if the index is not the final one like so: var options = { type: 'line', data: { labels: ["Red", "Blue", "Yellow", "Green", "Purple", "Orange"], datasets: [{ label: '# of Votes', data: [12, 19, 3, 5, 2, 3], borderWidth: 1 }, { label: '# of Points', data: [7, 11, 5, 8, 3, 7], borderWidth: 1 } ] }, options: { scales: { y: { ticks: { callback: (val, i, ticks) => (i < ticks.length - 1 ? val : null) // Replace null by empty string to still show the gridLine } } } } } var ctx = document.getElementById('chartJSContainer').getContext('2d'); new Chart(ctx, options); <body> <canvas id="chartJSContainer" width="600" height="400"></canvas> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/3.3.2/chart.js"></script> </body>
ChartJS Separate Labels for each dataset/independent datasets?
I'm essentially attempting to create a bar chart with 2-8 items where the label on the bottom/legend is the short product code(ex: 4380) and mousing over the bar shows the full SKU/product name. I have gotten it mostly working but my implementation goes one of two undesirable ways. The data points all combine into the first product number/chart label. The blank spots make the bars tiny/not fill up the full width. My code for rendering the chart is as follows: var myBarChart2; $.ajax({ url: "chartdata.php", data: { "skugroup": group }, method: 'GET', dataType: 'json', success: function (d) { Chart.defaults.global.defaultFontFamily = '-apple-system,system-ui,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif'; Chart.defaults.global.defaultFontColor = '#292b2c'; var ctx = document.getElementById("inventorybarchart"); myBarChart2 = new Chart(ctx, { type: 'bar', data: { labels: d.labels, datasets: d.datasets, }, options: { scales: { xAxes: [{ gridLines: { display: false }, ticks: { display: true } }], yAxes: [{ ticks: { min: 0, beginAtZero: true }, gridLines: { display: true } }], }, legend: { display: false } } }); } }); The ajax response for the two versions is as follows: Version 1: {"datasets":[{"labels":"GRAY-DARK-GRAY","backgroundColor":"rgba(164,222,164,1)","borderColor":"rgba(164,222,164,1)","data":[5996]},{"labels":"CANARY-YELLOW","backgroundColor":"rgba(35,148,58,1)","borderColor":"rgba(35,148,58,1)","data":[4605]},{"labels":"PINK-WHITE-GRAY","backgroundColor":"rgba(101,24,125,1)","borderColor":"rgba(101,24,125,1)","data":[1288]},{"labels":"SEAFOAM-WHITE-GRAY","backgroundColor":"rgba(129,74,64,1)","borderColor":"rgba(129,74,64,1)","data":[3463]},{"labels":"YELLOW-WHITE-GRAY","backgroundColor":"rgba(91,216,70,1)","borderColor":"rgba(91,216,70,1)","data":[1537]},{"labels":"WHITE-YELLOW","backgroundColor":"rgba(101,225,237,1)","borderColor":"rgba(101,225,237,1)","data":[152]}],"labels":["4380","4311","4571","4588","4557","4373"]} Version 2: {"datasets":[{"label":"GRAY-DARK-GRAY","backgroundColor":"rgba(1,1,235,1)","borderColor":"rgba(1,1,235,1)","data":[5996,null,null,null,null]},{"label":"CANARY-YELLOW","backgroundColor":"rgba(12,87,184,1)","borderColor":"rgba(12,87,184,1)","data":[null,4605,null,null,null]},{"label":"PINK-WHITE-GRAY","backgroundColor":"rgba(85,107,126,1)","borderColor":"rgba(85,107,126,1)","data":[null,null,1288,null,null]},{"label":"SEAFOAM-WHITE-GRAY","backgroundColor":"rgba(181,150,65,1)","borderColor":"rgba(181,150,65,1)","data":[null,null,null,3463,null]},{"label":"YELLOW-WHITE-GRAY","backgroundColor":"rgba(132,66,28,1)","borderColor":"rgba(132,66,28,1)","data":[null,null,null,null,1537]},{"label":"WHITE-YELLOW","backgroundColor":"rgba(49,195,217,1)","borderColor":"rgba(49,195,217,1)","data":[null,null,null,null,null]}],"labels":["4380","4311","4571","4588","4557","4373"]} The only difference is either I always use the 0 indexes for datasets[index].data or I fill in null depending on where it should be. Should I be changing the way the chart is rendered or should I change the way the data is passed in? For the record, the mouseover shows the proper sku/full name.
I would define the data in a single dataset and keep the full product names in a separate property. const data = { "labels": ["4380", "4311", "4571", "4588", "4557", "4373"], "productNames": ["GRAY-DARK-GRAY", "CANARY-YELLOW", "PINK-WHITE-GRAY", "SEAFOAM-WHITE-GRAY", "YELLOW-WHITE-GRAY", "WHITE-YELLOW"], "datasets": [{ "data": [5996, 4605, 1288, 3463, 1537, 152], ... }] }; To get the product names displayed in the tooltip, you would have to define a label callback function as follows: tooltips: { callbacks: { label: (tooltipItem, data) => { let i = tooltipItem.index; return data.productNames[i] + ': ' + data.datasets[0].data[i]; } } } Please take a look at your amended code and see how it works. const data = { "labels": ["4380", "4311", "4571", "4588", "4557", "4373"], "productNames": ["GRAY-DARK-GRAY", "CANARY-YELLOW", "PINK-WHITE-GRAY", "SEAFOAM-WHITE-GRAY", "YELLOW-WHITE-GRAY", "WHITE-YELLOW"], "datasets": [{ "data": [5996, 4605, 1288, 3463, 1537, 152], "backgroundColor": ["rgba(1,1,235,1)", "rgba(12,87,184,1)", "rgba(85,107,126,1)", "rgba(181,150,65,1)", "rgba(132,66,28,1)", "rgba(49,195,217,1)"], "borderColor": ["rgba(1,1,235,1)", "rgba(12,87,184,1)", "rgba(85,107,126,1)", "rgba(181,150,65,1)", "rgba(132,66,28,1)", "rgba(49,195,217,1)"] }] }; var ctx = document.getElementById("inventorybarchart"); myBarChart2 = new Chart(ctx, { type: 'bar', data: data, options: { scales: { xAxes: [{ gridLines: { display: false } }], yAxes: [{ ticks: { beginAtZero: true } }], }, legend: { display: false }, tooltips: { callbacks: { label: (tooltipItem, data) => { let i = tooltipItem.index; return data.productNames[i] + ': ' + data.datasets[0].data[i]; } } } } }); <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.0/Chart.min.js"></script> <canvas id="inventorybarchart" height="90"></canvas>
Chart displaying values outside the min and max ranges (Chart.js)
When I set a min and max value for my chart it still displays all the MIN values squished up to the left of my graph, but the max values disappear as they should. HTML <div id="graph"> <canvas id="line-chart" width="400" height="225"></canvas> </div> <button id="12hours">12 Hours</button> <button id="24hours">24 Hours</button> JS function displayGraph(object) { timestamp = getDataForGraph(object, 'timestamp'); temp1 = getDataForGraph(object, 'temp1'); temp2 = getDataForGraph(object, 'temp2'); temp3 = getDataForGraph(object, 'temp3'); var mychart = new Chart(document.getElementById("line-chart"), { type: 'line', data: { labels: timestamp, datasets: [{ data: temp1, label: "Temp 1", borderColor: "#ff0000", fill: false }, { data: temp2, label: "Temp 2", borderColor: "#3bff00", fill: false }, { data: temp3, label: "Temp 3", borderColor: "#00edff", fill: false } ] }, options: {responsive: true, maintainAspectRatio: false, scales: { xAxes: [{ ticks: { fontSize: 5 }, type: 'time', time: { unit: 'hour', displayFormats: { hour: 'HH:mm:ss' } } }], yAxes: [{ ticks: { fontSize: 5 } }] } } }); $('#12hours').off().on('click', function () { mychart.options.scales.xAxes[0].time.min = '2018-10-29 08:00:00'; mychart.options.scales.xAxes[0].time.max = '2018-10-29 20:00:00'; mychart.update(); }); $('#24hours').off().on('click', function () { mychart.options.scales.xAxes[0].time.min = '2018-10-29 00:00:00'; mychart.options.scales.xAxes[0].time.max = '2018-10-29 23:59:59'; mychart.update(); }); } Current output when using min and max values. would like to get rid of all the values before 08:00 that are showing up on the left hand side of the axes. What it looks like when max and min are placed What it looks like with no max or min placed
Stacked bar charts in chart.js with different values in stacks
I want to create a stack graph something like this: Note: Each stack has different value Is it possible with chart js ? If yes what my data should look like ? I have tried this: var data = { labels: ["2018", "2019"], //Want "value 1,2,3 for 2018 and value 4,5,6 for 2019" datasets: [ { label: "Harpo", fillColor: "blue", data: [] // What should i use here }, { label: "Chico", fillColor: "red", data: [] // What should i use here } ] }; But this is not what i want. Any help would be appreciated.
in order to have a stack of 3 bars, you will need 3 datasets. to have different colors, use an array for backgroundColor. see following working snippet... $(document).ready(function() { new Chart(document.getElementById("myChart").getContext("2d"), { type: "bar", data: { labels: ["2018", "2019"], datasets: [ { backgroundColor: ["#673AB7", "#90A4AE"], fillColor: "#000000", data: [1, 4] }, { backgroundColor: ["#E1BEE7", "#0D47A1"], data: [2, 5] }, { backgroundColor: ["#BA68C8", "#455A64"], data: [3, 6] } ] }, options: { legend: { display: false }, scales: { xAxes:[{ stacked: true }], yAxes:[{ stacked: true }], } } }); }); <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.2/Chart.bundle.min.js"></script> <canvas id="myChart"></canvas>
Make Chart.js horizontal bar labels multi-line
Just wondering if there is any way to set the horizontal bar labels for y-axis using chart.js. Here is how I set up the chart: <div class="box-body"> <canvas id="chart" style="position: relative; height: 300px;"></canvas> </div> Javascript: var ctx = document.getElementById('chart').getContext("2d"); var options = { layout: { padding: { top: 5, } }, responsive: true, animation: { animateScale: true, animateRotate: true }, }; var opt = { type: "horizontalBar", data: { labels: label, datasets: [{ data: price, }] }, options: options }; if (chart) chart.destroy(); chart= new Chart(ctx, opt); chart.update(); As you all can see, the first and third labels are too long and cut off. Is there a way to make the label multi-line?
If you want to have full control over how long labels are broken down across lines you can specify the breaking point by providing labels in a nested array. For example: var chart = new Chart(ctx, { ... data: { labels: [["Label1 Line1:","Label1 Line2"],["Label2 Line1","Label2 Line2"]], datasets: [{ ... });
You can use the following chart plugin : plugins: [{ beforeInit: function(chart) { chart.data.labels.forEach(function(e, i, a) { if (/\n/.test(e)) { a[i] = e.split(/\n/); } }); } }] add this followed by your chart options ᴜꜱᴀɢᴇ : add a new line character (\n) to your label, wherever you wish to add a line break. ᴅᴇᴍᴏ var chart = new Chart(ctx, { type: 'horizontalBar', data: { labels: ['Jan\n2017', 'Feb', 'Mar', 'Apr'], datasets: [{ label: 'BAR', data: [1, 2, 3, 4], backgroundColor: 'rgba(0, 119, 290, 0.7)' }] }, options: { scales: { xAxes: [{ ticks: { beginAtZero: true } }] } }, plugins: [{ beforeInit: function(chart) { chart.data.labels.forEach(function(e, i, a) { if (/\n/.test(e)) { a[i] = e.split(/\n/); } }); } }] }); <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.6.0/Chart.min.js"></script> <canvas id="ctx"></canvas>