1👍
The error in your code is in the function render
. You send the chartUI
to the function as an argument and then inside the function you assign it a new Chart
. Thus, the value of chartUI
in the function and the value outside are different (you probably assumed the assigned value will be available outside the scope of the function, like it’s the case with references in other programming languages).
Then, the destroy
function is always called on the same chartUI
object, and has no effect in actually destroying the real active chartUI
which was created in render
.
You can verify this by logging chartUI.canvas
in the destroy
function – you’ll see that the first time you get the canvas element from the html, but the second time the canvas is null
– that’s because the object referenced by chartUI
is the same from the previous call and not the new one created by new Chart
.
So, a quick fix would be to add a return chartUI;
at the end of the function render
:
function render(currentAccount, chartUI) {
chartUI = new Chart(document.getElementById("chart"), config);
//...................
chartUI.update();
return chartUI;
}
and then recover the newly created chart object with:
chartUI = render(currentAccount, chartUI);
in updateUI
; jsFiddle.
However, the whole destroy and recreate pattern is not required for the type of data you are using (and in my experience hardly anytime actually); it also results in a non-smooth visual transition.
It is sufficient to just assign new data and call update
, like in this snippet:
let t0 = Date.now();
const currentAccountGen = ()=>{t0 += 2*24*1000*3600; return {
transactions: Array.from({length: 10},
(_, i)=>({date: t0+i*24*1000*3600, amount: 10+2*Math.random()+3*Math.cos(i/10*Math.PI)}))
}};
let labelArr = [];
let dataArr = [];
let data = {
labels: labelArr,
datasets: [
{
data: dataArr,
label: "# of Amount",
borderWidth: 1,
borderColor: "#01a001",
backgroundColor: "#01a001",
},
],
};
let config = {
type: "line",
data,
options: {
scales: {
x: {
type: "time",
},
y: {
// beginAtZero: false, // default
},
},
},
};
const chartUI = new Chart(document.getElementById("chart"), config);
function render(currentAccount, chartUI) {
labelArr = [];
dataArr = [];
currentAccount.transactions.forEach((t) => {
const dateReady = /*currentUser.dateCreator*/(t.date);
labelArr.push(dateReady);
dataArr.push(t.amount);
});
chartUI.data.datasets[0].data = dataArr;
chartUI.data.labels = labelArr;
chartUI.update();
}
render(currentAccountGen(), chartUI);
const hi = setInterval(function(){
render(currentAccountGen(), chartUI);
}, 1000)
function stop(){
clearInterval(hi);
document.querySelector('#stopBut').disabled = true;
}
<button id='stopBut' onclick="stop()">Stop</button>
<div style="height:250px">
<canvas id="chart"></canvas>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.3.0/chart.umd.js" integrity="sha512-CMF3tQtjOoOJoOKlsS7/2loJlkyctwzSoDK/S40iAB+MqWSaf50uObGQSk5Ny/gfRhRCjNLvoxuCvdnERU4WGg==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>