How to rerender the line chart based on data change in vue-chartjs?

175 views Asked by At

I am creating a component ScatterChart.vue within my Nuxt 3 or Vue 3 application and I am sending value to it from the parent component based on which I want the line graph to be drawn. Currently, I am able to get the data in the child component but it's not drawing any graph neither its throwing any error.

I believe I need to destroy and recreat it but unable to understand how.

Following is my parent component: components/Parent.vue:

<template>
<button
type="button"
@click="getData"
>GET DATA</button>
<!-- Chart based on values -->
<ScatterChart :chartData="chartData" />
</template>

<script setup>
//Chart related variables
const chartData = useState("chartData", () => ({ labels: [], datasets: [] }));
const datasetColors = useState("datasetColors", () => [
  "#FF6384",
  "#36A2EB",
  "#FFCE56",
  "#4BC0C0",
]);

function getData(){
//read some file and get data and populate timeValues and then assign to chartData
if (!chartData.value.labels.includes(dateString)) {
  chartData.value.labels.push(dateString);
}

chartData.value.datasets.push({
    label: "TIME ",
    type: "line",
    borderColor: datasetColors[chartData.value.datasets.length + 1],
    backgroundColor: datasetColors[chartData.value.datasets.length + 1],
    borderWidth: 1,
    data: timeValues,
  });
}

components/ScatterChart.vue:

<template>
  <div class="line-chart dark:bg-gray-800 dark:text-white">
    <Line :data="chartData" :options="chartOptions" />
  </div>
</template>

<script setup>
import { Line } from "vue-chartjs";
import {
  Chart as ChartJS,
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend,
} from "chart.js";
import { ref, watch, onMounted } from "vue";

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
);
const chartOptions = {
  responsive: true,
  maintainAspectRatio: false,
};

const props = defineProps({
  chartData: {
    type: Array, //Data for the chart
    required: false,
  },
});

const chartData = ref(props.chartData);
const lineChart = ref(null);
const chartInstance = ref(null);

onMounted(() => {
  if (chartInstance.value) {
    chartInstance.value.destroy();
  }
  if (chartData.value && chartData.value.datasets.length > 0) {
    chartInstance.value = new Line(lineChart.value, {
      data: chartData.value,
      options: chartOptions,
    });
  }
});

watch(
  () => props.chartData,
  (newData) => {
    chartData.value = newData;
    if (chartInstance.value) {
      chartInstance.value.destroy();
    }
    if (chartData.value && chartData.value.datasets.length > 0) {
      chartInstance.value = new Line(lineChart.value, {
        data: chartData.value,
        options: chartOptions,
      });
    }
  }
);
</script>

I am unable to to trigger the method onMounted or the watcher within child component but if I log the values in template then able to see the values:

<template>
{{chartData}}
  <div class="line-chart dark:bg-gray-800 dark:text-white">
    <Line :data="chartData" :options="chartOptions" />
  </div>
</template>
0

There are 0 answers