Reputation: 4364
I created the following question Horizontal overlapping of bars, not whole graph which was kindly answered (I was advised to create a new question!). Whilst the answer worked great - I have 2x charts on the same page which for some reason throws a Cannot read property 'data' of undefined
error.
I don't want to include the entirity of my 2 charts but the afterUpdate code that moves the bars is as follows:
function(chart) {
var datasets = chart.config.data.datasets;
console.log(datasets);
for (let iDs = 1; iDs < datasets.length; iDs++) {
let dataset = datasets[iDs];
// I added the following line however stacks the graph and doesn't display it correctly like the first
if (typeof dataset._meta[0] !== 'undefined'){
for (var i = 0; i < dataset._meta[0].data.length; i++) {
let model = dataset._meta[0].data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
}
I have added the typeof
check to the code which at least renders the graph, however I would like both graphs to function the same way whereas the addition of the typeof check then just stacks the graph and ignores the code to move the bars.
This can best be seen in action in the following fiddle: https://jsfiddle.net/ycpj7g8w/
Upvotes: 0
Views: 868
Reputation: 26190
The described behavior is weird, given that both charts work fine if they're created isolated from each other. The problem can be solved by changing the afterUpdate
function and make use of the chart's .getDatasetMeta(index)
function to obtain the dataset's metadata.
afterUpdate: function(chart) {
let datasets = chart.config.data.datasets;
for (let iDs = 1; iDs < datasets.length; iDs++) {
let meta = chart.getDatasetMeta(iDs);
for (var i = 0; i < meta.data.length; i++) {
let model = meta.data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
Please take a look at your amended and runnable code below:
Chart.defaults.global.legend.labels.usePointStyle = true;
Chart.defaults.scale.gridLines.drawOnChartArea = false;
var offset = 6;
new Chart('graph_1', {
"type": "bar",
"data": {
"labels": ["2020-08-01", "2020-09-01", "2020-10-01"],
"datasets": [{
"label": "Title test 1",
"data": [30, 20, 60],
"xAxisID": "bar-x-axis-1",
"barThickness": 14,
"backgroundColor": "rgba(241,213,157,1)",
"borderColor": "rgba(241,213,157,1)",
"pointBackgroundColor": "rgba(241,213,157,1)"
},
{
"label": "Title test 2",
"data": [30, 20, 60],
"xAxisID": "bar-x-axis-2",
"barThickness": 14,
"backgroundColor": "rgba(237,141,120,1)",
"borderColor": "rgba(237,141,120,1)",
"pointBackgroundColor": "rgba(237,141,120,1)"
},
{
"label": "Title test 3",
"data": [30, 20, 60],
"xAxisID": "bar-x-axis-3",
"barThickness": 14,
"backgroundColor": "rgba(120,199,212,1)",
"borderColor": "rgba(120,199,212,1)",
"pointBackgroundColor": "rgba(120,199,212,1)"
}
]
},
"plugins": [{
"afterUpdate": function(chart) {
let datasets = chart.config.data.datasets;
for (let iDs = 1; iDs < datasets.length; iDs++) {
let meta = chart.getDatasetMeta(iDs);
for (var i = 0; i < meta.data.length; i++) {
let model = meta.data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
}],
"curvature": 0.2,
"options": {
"legend": {
"display": true,
"position": "bottom"
},
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true,
"stepSize": 25
}
}],
"xAxes": [{
"id": "bar-x-axis-3",
"display": false
},
{
"id": "bar-x-axis-2",
"display": false,
"offset": true
},
{
"id": "bar-x-axis-1",
"display": false,
"offset": true
}
]
},
"barRoundness": 0.5
}
});
new Chart('graph_2', {
"type": "bar",
"data": {
"labels": ["2020-06-01", "2020-07-01", "2020-08-01", "2020-09-01", "2020-10-01"],
"datasets": [{
"label": "Stage 1",
"data": [30, 75, 60, 90],
"xAxisID": "bar-x-axis-1",
"barThickness": 14,
"backgroundColor": "rgba(241,213,157,1)",
"borderColor": "rgba(241,213,157,1)",
"pointBackgroundColor": "rgba(241,213,157,1)"
},
{
"label": "Stage 2",
"data": [40, 66, 60, 90],
"xAxisID": "bar-x-axis-2",
"barThickness": 14,
"backgroundColor": "rgba(237,141,120,1)",
"borderColor": "rgba(237,141,120,1)",
"pointBackgroundColor": "rgba(237,141,120,1)"
},
{
"label": "Stage 3",
"data": [50, 45, 60, 90],
"xAxisID": "bar-x-axis-3",
"barThickness": 14,
"backgroundColor": "rgba(120,199,212,1)",
"borderColor": "rgba(120,199,212,1)",
"pointBackgroundColor": "rgba(120,199,212,1)"
},
{
"label": "Stage 4",
"data": [60, 35, 60, 90],
"xAxisID": "bar-x-axis-4",
"barThickness": 14,
"backgroundColor": "rgba(5,114,159,1)",
"borderColor": "rgba(5,114,159,1)",
"pointBackgroundColor": "rgba(5,114,159,1)"
},
{
"label": "Stage 5",
"data": [70, 25, 60, 90],
"xAxisID": "bar-x-axis-5",
"barThickness": 14,
"backgroundColor": "rgba(2,41,112,1)",
"borderColor": "rgba(2,41,112,1)",
"pointBackgroundColor": "rgba(2,41,112,1)"
}
]
},
"plugins": [{
"afterUpdate": function(chart) {
let datasets = chart.config.data.datasets;
for (let iDs = 1; iDs < datasets.length; iDs++) {
let meta = chart.getDatasetMeta(iDs);
for (var i = 0; i < meta.data.length; i++) {
let model = meta.data[i]._model;
model.x += iDs * offset;
model.controlPointNextX += iDs * offset;
model.controlPointPreviousX += iDs * offset;
}
}
}
}],
"curvature": 0.2,
"options": {
"legend": {
"display": true,
"position": "bottom"
},
"scales": {
"yAxes": [{
"ticks": {
"beginAtZero": true,
"stepSize": 25
}
}],
"xAxes": [{
"id": "bar-x-axis-5",
"display": false,
},
{
"id": "bar-x-axis-4",
"display": false,
"offset": true
},
{
"id": "bar-x-axis-3",
"display": false,
"offset": true
},
{
"id": "bar-x-axis-2",
"display": false,
"offset": true
},
{
"id": "bar-x-axis-1",
"display": false,
"offset": true
}
]
},
"barRoundness": 0.5
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js"></script>
<canvas id="graph_1"></canvas>
<canvas id="graph_2"></canvas>
Please note that when all charts contained on a page use the same plugin function, you don't have to repeat the code but can simply register it once through
Chart.pluginService.register
as shown in this answer.
Upvotes: 2