I have a problem that I'm trying to solve. Cannot read property of null (read 'conversion'). What does it mean? . I checked the option of integrating mychart.update() from this question https://github.com/chartjs/Chart.js/issues/5149. But when I try to start I get other errors.
TypeError: Cannot read properties of null (reading 'length') at Object.acquireContext (Chart.js?473e:7756:1) at Chart.construct (Chart.js?473e:9324:1) at new Chart (Chart.js?473e:9311:1) at VueComponent.draw (Analytics-test.vue?b2a7:69:1) at VueComponent.loadTrainings (Analytics-test.vue?b2a7:444:1) at async VueComponent.mounted (Analytics-test.vue?b2a7:476:1)
Below you can see the last code I tried to launch.
<template> <div> Прибыль/посещаемость <div class="small"> <canvas id="mychart" height="400"></canvas> </div> </div> </template> <script> import Chart from 'chart.js' export default { data: () => ({ flagStartDate: false, chartData: null, labels: [], dataset: {}, draftData: null, data: [], datacollection: [], clubsId: ['5c3c5e12ba86198828baa4a7', '5c3c5e20ba86198828baa4c5', '60353d6edbb58a135bf41856', '61e9995d4ec0f29dc8447f81', '61e999fc4ec0f29dc844835e'], // clubsId: ['5c3c5e12ba86198828baa4a7', '61e999fc4ec0f29dc844835e'], // clubsId: ['61e999fc4ec0f29dc844835e'], }), methods: { draw() { if (this.mychart) { this.mychart.destroy(); } const ctx = document.getElementById('main-chart'); this.mychart = new Chart(ctx, { type: 'line', data: { labels: this.labels, datasets: this.datacollection }, options: { responsive: true, elements: { line: { tension: 0 // disables bezier curves } }, scales: { xAxes: [{ type: "time", display: true, scaleLabel: { display: true, labelString: 'Time' }, ticks: { major: { fontStyle: "bold", fontColor: "#FF0000" } } }], yAxes: [{ display: true, scaleLabel: { display: true, labelString: this.labelY }, ticks: { min: 0, // it is for ignoring negative step. beginAtZero: true, stepSize: 1 // if i use this it always set it '1', which look very awkward if it have high value e.g. '100'. } }] } } }); }, participantsCountClub(clubId) { switch (clubId) { case '5c3c5e12ba86198828baa4a7': return { label: "Тренировок на Фрунзенской", borderColor: "#3e95cd", fill: false } case '5c3c5e20ba86198828baa4c5': return { label: "Тренировок на Чернышевской", borderColor: "#8e5ea2", fill: false }; case '60353d6edbb58a135bf41856': return { label: "Тренировок на Василеостровской", borderColor: "#e8c3b9", fill: false }; case '61e9995d4ec0f29dc8447f81': return { label: "Тренировок на Московской", borderColor: "#3cba9f", fill: false }; case '61e999fc4ec0f29dc844835e': return { label: "Тренировок на Лесной", borderColor: "#c45850", fill: false }; default: return 'Неизвестный клуб'; } }, async loadTrainings(clubsId) { try { for (let clubId in clubsId) { clubId = clubsId[clubId] let dateFrom = '2021-06-01T00:00:00' let dateTo = '2022-08-01T23:59:59' let groupBy = 'month' await this.$store.dispatch('loadAvgSchedule', { clubId, dateFrom, dateTo, groupBy }) this.draftData = this.$store.state.avgShedule if (this.labels.length === 0) { this.getDatesAvgIncome() } this.flagStartDate = true await this.getParticipantsCount(clubId) this.flagStartDate = false } this.draw() } catch (e) { console.error(e) } }, async getParticipantsCount(clubId) { for (let item in this.draftData) { let positionDate = this.labels.indexOf(this.draftData[item].date.slice(0, 7)) if (this.flagStartDate && positionDate > 0) { let zerroArray = await this.bindDataDates(positionDate) this.data = this.data.concat(zerroArray) } this.data.push(this.draftData[item].participantsCount) this.flagStartDate = false } this.dataset.data = this.data Object.assign(this.dataset, this.participantsCountClub(clubId)) this.datacollection.push(this.dataset) console.log('this.datacollection', this.datacollection) this.data = [] this.dataset = {} }, }, async mounted() { await this.loadTrainings(this.clubsId) }, } </script> <style> .small { max-width: 600px; margin: 150px auto; } </style>
I also tried this option (using update()):
<template> <div> Прибыль/посещаемость <div class="small"> <canvas id="mychart" height="400"></canvas> </div> </div> </template> <script> import Chart from 'chart.js' export default { data: () => ({ flagStartDate: false, chartData: null, labels: [], dataset: {}, draftData: null, data: [], datacollection: [], clubsId: ['5c3c5e12ba86198828baa4a7', '5c3c5e20ba86198828baa4c5', '60353d6edbb58a135bf41856', '61e9995d4ec0f29dc8447f81', '61e999fc4ec0f29dc844835e'], // clubsId: ['5c3c5e12ba86198828baa4a7', '61e999fc4ec0f29dc844835e'], // clubsId: ['61e999fc4ec0f29dc844835e'], }), methods: { draw() { if (this.mychart) { this.mychart.destroy(); } const ctx = document.getElementById('main-chart'); this.mychart = new Chart(ctx, { type: 'line', data: { labels: this.labels, datasets: this.datacollection }, options: { responsive: true, elements: { line: { tension: 0 // disables bezier curves } }, scales: { xAxes: [{ type: "time", display: true, scaleLabel: { display: true, labelString: 'Time' }, ticks: { major: { fontStyle: "bold", fontColor: "#FF0000" } } }], yAxes: [{ display: true, scaleLabel: { display: true, labelString: this.labelY }, ticks: { min: 0, // it is for ignoring negative step. beginAtZero: true, stepSize: 1 // if i use this it always set it '1', which look very awkward if it have high value e.g. '100'. } }] } } }); }, participantsCountClub(clubId) { switch (clubId) { case '5c3c5e12ba86198828baa4a7': return { label: "Тренировок на Фрунзенской", borderColor: "#3e95cd", fill: false } case '5c3c5e20ba86198828baa4c5': return { label: "Тренировок на Чернышевской", borderColor: "#8e5ea2", fill: false }; case '60353d6edbb58a135bf41856': return { label: "Тренировок на Василеостровской", borderColor: "#e8c3b9", fill: false }; case '61e9995d4ec0f29dc8447f81': return { label: "Тренировок на Московской", borderColor: "#3cba9f", fill: false }; case '61e999fc4ec0f29dc844835e': return { label: "Тренировок на Лесной", borderColor: "#c45850", fill: false }; default: return 'Неизвестный клуб'; } }, async loadTrainings(clubsId) { try { for (let clubId in clubsId) { clubId = clubsId[clubId] let dateFrom = '2021-06-01T00:00:00' let dateTo = '2022-08-01T23:59:59' let groupBy = 'month' await this.$store.dispatch('loadAvgSchedule', { clubId, dateFrom, dateTo, groupBy }) this.draftData = this.$store.state.avgShedule if (this.labels.length === 0) { this.getDatesAvgIncome() } this.flagStartDate = true await this.getParticipantsCount(clubId) this.flagStartDate = false } // Below I tried refresh charts after updates data this.mychart.update() } catch (e) { console.error(e) } }, async getParticipantsCount(clubId) { for (let item in this.draftData) { let positionDate = this.labels.indexOf(this.draftData[item].date.slice(0, 7)) if (this.flagStartDate && positionDate > 0) { let zerroArray = await this.bindDataDates(positionDate) this.data = this.data.concat(zerroArray) } this.data.push(this.draftData[item].participantsCount) this.flagStartDate = false } this.dataset.data = this.data Object.assign(this.dataset, this.participantsCountClub(clubId)) this.datacollection.push(this.dataset) console.log('this.datacollection', this.datacollection) this.data = [] this.dataset = {} }, }, async mounted() { await this.loadTrainings(this.clubsId) this.draw() }, } </script> <style> .small { max-width: 600px; margin: 150px auto; } </style>
When I open the string in the debugger:
You can see a reference to this line:
If checking the last reference:
You can see this line:
P粉8514014752023-11-05 10:04:31
The property length is for an Array and the error states that length cannot be read of null (the important thing is the word "null"), so the problem is that the const or var with that property becomes null for whatever reason. p>
P粉0716263642023-11-05 00:11:54
The problem is with the template. I forgot to write the correct ID for the canvas. It must be like this:
<canvas id="main-chart" height="400"></canvas>