victorgarciaesgi / vue-chart-3

📊 A simple wrapper around Chart.js 3 for Vue 2 & 3

Home Page:https://vue-chart-3.netlify.app/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ref.chartInstance always null

Mootook opened this issue · comments

Hello, thanks for this package. I started using it on my team lately, and it's great!

However, I'm wondering if I'm doing something wrong or if there's an issue with the properties.
I use a ref on my component instance and am trying to access the chartInstance so that I can retrigger an update when one of my props changes (none of the data, just a background color for a dynamically drawn gradient).

Something like

<template>
  <Bar :data="data" ref="chartRef" />
</template>

<script>
setup () {
  const chartRef = ref(null)

  watch(barColorPreference, () => {
    const chartInstance = chartRef.value.chartInstance // this is always null
  })

  const data = computed(() => ({ })) // all my data

  return { chartRef, data }
}
</script>

The README.md specifies that I should be able to access the chartInstance this way. Am I missing something?

I forked the CodeSandbox from the README.md
https://codesandbox.io/s/demo-vue-chart-3-forked-y6jvv?file=/src/App.vue

Hi @Mootook and thanks!
You're not doing anything wrong, accessing chartInstance has been implemented today thanks to this issue #4 but I forgot to update the docs.
But there is still bugs because making chartInstance reactive will throw an error in Vue 3 and not in Vue 2 :(
I will work on a solution making chartInstance reactive only for Vue 2.

The workaround for now is using the events chart:render or chart:update like this:

<template>
  <div>
    <DoughnutChart
      ref="doughnutRef"
      :data="testData"
      @chart:render="handleChartRender"
    />
    <button @click="shuffleData">Shuffle</button>
  </div>
</template>

<script lang="ts">
import { shuffle } from 'lodash';
import { computed, defineComponent, ref } from 'vue';
import { Doughnut } from 'vue-chart-3';
import { Chart, ChartData, ChartOptions } from 'chart.js';

export default defineComponent({
  name: 'Home',
  components: { DoughnutChart: Doughnut },
  setup() {
    const data = ref([30, 40, 60, 70, 5]);
    const doughnutRef = ref<typeof Doughnut>();
    const testData = computed<ChartData<'doughnut'>>(() => ({
      labels: ['Paris', 'Nîmes', 'Toulon', 'Perpignan', 'Autre'],
      datasets: [
        {
          data: data.value,
          backgroundColor: ['#77CEFF', '#0079AF', '#123E6B', '#97B0C4', '#A5C8ED'],
        },
      ],
    }));

    function handleChartRender(chart: Chart<'doughnut'>) {
      console.log(chart);
    }

    function shuffleData() {
      data.value = shuffle(data.value);
    }

    return { testData, shuffleData, doughnutRef, handleChartRender };
  },
});
</script>

By the way the data in each Chart Component is already reactive to changes! If your data changes, the Chart will update itself like in the exemples :)

Docs updated!

@victorgarciaesgi Ah, that makes sense. Thanks!

Also, my use case does not involve changing the data. I'm allowing for dynamically setting the background color of a BarChart while keeping the data consistent.
This is perhaps not in the bounds of this issue, but my current implementation is something like

watch(barColorPreference, async newColor => {
  data.labels = [] // clear and await the render to rerender the chart
  await nextTick()
  data.label = originalLabels
})

I assume there's a much better way.

Okay! Does the workaround is okay for you ? (with the events)

@victorgarciaesgi yup! Thanks again