I'm using vue to display the data using dynamical line chart with VUE. In parent vue, I'm requesting the server to get each data point, and then pass them to the child VUE. Now I come across an issue when displaying the data point in child VUE, "Uncaught TypeError: myChart.value.setOption is not a function". The child VUE cold is as follows, it is very strange, in function startDataGeneration(), myChart.value changed from eChart object to '..'. the console is as shown below, however, if I remove the parameters in parents VUE (e.g , this issue doesn't exist, but I cannot remove it because I need to pass the data to the child VUE.
//In parent.VUE
<DashGPUPowerUsage :gpuPower="state.gpuPower" :isGPUPowerLoading="state.isGPUPowerLoading" />
//This is child VUE DashGPUPowerUsage.vue
<template>
<div ref="myChart" style="width: 100%; height: 400px;"></div>
</template>
<script setup>
import { onMounted, ref, watch } from 'vue';
import * as echarts from 'echarts';
const props = defineProps({
gpuPower: null,
isGPUPowerLoading: Boolean,
});
// Create a reference for the chart container
const myChart = ref(null);
let seriesData = ref([]);
const isFirstUpdate = ref(true);
const initChart = () => {
myChart.value = echarts.init(myChart.value);
// Set an initial chart option, without any series data yet
myChart.value.setOption({
title: {
text: "Dynamic Data & Time Axis",
},
tooltip: {
trigger: "axis",
formatter: (params) => {
return params
.map(
(param) =>
`${param.seriesName}<br/>Time: ${param.name}<br/>Value: ${param.value[1].toFixed(
3
)}`
)
.join("<br/>");
},
axisPointer: {
animation: false,
},
},
xAxis: {
type: "time",
boundaryGap: false,
data: [], // Initial empty data
},
yAxis: {
type: "value",
boundaryGap: [0, "100%"],
},
series: [], // Empty series initially
});
};
const generateNewData = () => {
for (const hostIp in props.gpuPower) {
const hostData = props.gpuPower[hostIp];
if (hostData && hostData.data && Array.isArray(hostData.data.result)) {
const resultData = hostData.data.result;
resultData.forEach((gpuInfo) => {
const uuid = gpuInfo.metric.UUID;
const timestamp = gpuInfo.value[0];
const powerUsage = parseFloat(gpuInfo.value[1]);
const date = new Date(timestamp * 10000);
const currentSeriesData = seriesData.value.find((series) => series.uuid === uuid);
if (currentSeriesData) {
currentSeriesData.data.push({
name: date.toString(),
value: [date, powerUsage]
});
//set max Data Points to be shown in the chart
if (currentSeriesData.data.length > 2000) {
currentSeriesData.data.shift();
}
} else {
seriesData.value.push({
name: gpuInfo.metric.modelName,
uuid: uuid,
type: 'line',
showSymbol: false,
data: [
{
name: date.toDateString(),
value: [date, powerUsage]
}
]
})
}
})
}
}
}
const updateChart = () => {
if (!seriesData.value) return; // If seriesData is null, skip the update
myChart.value.setOption({
xAxis: {
data: seriesData.value[0].data.map((item) => item.value[0]),
},
series: seriesData.value,
});
};
const startDataGeneration = () => {
console.log('BEFORE POWER: ', myChart.value)
setInterval(() => {
console.log('AFTER POWER: ', myChart.value)
generateNewData();
updateChart();
}, 1000); // Update chart every second
};
onMounted(() => {
// Initialize seriesData to an array once the component is mounted
seriesData.value = [
{
"name": "NVIDIA GeForce RTX 3090",
"uuid": "GPU-eaff73fa-41bd-b365-3f0d-a3bb4c921c48",
"type": "line",
"showSymbol": false,
"data": [
{
"name": "Sun Sep 04 2518",
"value": [
"2518-09-05T02:30:34.560Z",
17.668
]
}
]
},
{
"name": "NVIDIA RTX A6000",
"uuid": "GPU-3a679677-ef7f-78ee-217e-a1552b8e79f1",
"type": "line",
"showSymbol": false,
"data": [
{
"name": "Sun Sep 04 2518",
"value": [
"2518-09-05T02:30:34.489Z",
26.318
]
}
]
},
{
"name": "NVIDIA GeForce RTX 3090",
"uuid": "GPU-ff3ad650-f347-686c-e061-a287e28136e2",
"type": "line",
"showSymbol": false,
"data": [
{
"name": "Sun Sep 04 2518",
"value": [
"2518-09-05T02:30:34.489Z",
10.42
]
}
]
},
{
"name": "NVIDIA A100-PCIE-40GB",
"uuid": "GPU-17f4ff58-3e4e-eb03-d93f-65eafd6c9068",
"type": "line",
"showSymbol": false,
"data": [
{
"name": "Sun Sep 04 2518",
"value": [
"2518-09-05T02:30:34.489Z",
39.201
]
}
]
},
{
"name": "Tesla V100-PCIE-16GB",
"uuid": "GPU-a4388fa4-5170-baea-3e17-cdc3b0adbf94",
"type": "line",
"showSymbol": false,
"data": [
{
"name": "Sun Sep 04 2518",
"value": [
"2518-09-05T02:30:34.489Z",
36.936
]
}
]
}
];
// Now that seriesData is initialized, set the chart and start data generation
initChart();
startDataGeneration();
});
</script>
Explain why this happens, or how I can pass the data in correctly?
myChart
is template ref and shouldn't be manually overwritten. There is no need to make chart instance reactive, so it can be just a variable and not a ref:
let chartInstance;
const initChart = () => {
chartInstance = echarts.init(myChart.value);
chartInstance.setOption(...);
...
There is third-party vue-echarts
library that handles this.