Open tonylee00111 opened 1 year ago
I'm seeing the same thing when using Vue 2.7 and this.$refs.refname.chart
. the object key exists but is always null
Hm thats weird. Because if you console.log myChart.value
it shows the chart
attribute. I will look into it.
It seems that chart
is not available when onMounted
is called.
If you use nextTick
, then you can access the chart
object.
onMounted(async () => {
await nextTick()
console.log('test: ', mychart.value.chart);
})
I'm seeing the same behavior when running in <script setup>
. When logging the chart ref in onExportImageClick
it's always undefined.
EDIT: I found a way seconds after posting. So the ref
isn't bound the same way in Composition as it would be in Options API, but accessing the ref and instead looking at chartInstance
solved my problem. Code updated with working example:
<template>
<div class="relative ">
<PieChart
ref="chart"
:chart-data="chartData"
:options="chartOptions"
:height="height"
:css-classes="cssClasses"
/>
<div class="absolute top-0 right-0 px-2 py-1 space-x-2">
<OutlineButton size="xs" class="py-1.5 !px-1.5 !text-base">
<Fa :icon="['far','file-csv']" fixed-width />
</OutlineButton>
<OutlineButton
size="xs"
class="py-1.5 !px-1.5 !text-base"
@click="onExportImageClick"
>
<Fa :icon="['far','file-image']" fixed-width />
</OutlineButton>
</div>
</div>
</template>
<script setup>
import { Chart, registerables } from 'chart.js'
import { computed, nextTick, ref } from 'vue'
import { PieChart } from 'vue-chart-3'
import { emptyChartPlugin } from '@/Modules/Charts/ChartHelpers'
import OutlineButton from '../OutlineButton.vue'
Chart.defaults.font.family = 'Inter'
Chart.register(...registerables, emptyChartPlugin)
const props = defineProps({
options: {
type: Object,
default: null,
},
data: {
type: Object,
default: null,
},
height: {
type: Number,
default: 400,
},
cssClasses: {
type: String,
default: '',
},
})
const chart = ref(null)
const chartData = computed(() => {
return props.data
})
const chartOptions = computed(() => {
return props.options
})
const onExportImageClick = () => {
//Correctly logs Chart instance for interaction
console.log(chart.value.chartInstance)
}
</script>
Isn't the property name chart
instead of chartInstance
?
Ex: chart.value.chart
Isn't the property name
chart
instead ofchartInstance
? Ex:chart.value.chart
No, for some reason it isn't reflected like that when using Composition API.
@dnkmdg You are using vue-chart3
which is no longer maintained! Recommended is to use vue-chartjs
.
I just started with migrating. from vue-chart3
Is there also a composition example preferably in typescript?
Something like:
<script setup lang="ts">
import { Line, Pie, } from "vue-chartjs"
</script>
I'm seeing the same situation in the options api.
I wanted to listen to clicks on the points of a scatter plot, and thus wanted to access the chart. But during mounted()
the chart property of the ref returns as null
. More precisely, it returns as a proxy with this structure in the dev-tools:
Proxy { <target>: Proxy, <handler>: {…} }
<target>: Proxy { <target>: {…}, <handler>: {…} }
<target>: Object { chart: {…}, … }
__v_skip: true
chart: Object { __v_isShallow: true, dep: undefined, __v_isRef: true, … }
<prototype>: Object { … }
<handler>: Object { get: get(target, key, receiver), set: set(target, key, value, receiver)
}
<handler>: Object { get: get(target, key), has: has(target, key) }
And when trying to access the chart property, that property (at least during mounted
the chart is null.
I'm actually happy for any hints as to how to listen to clicks on the chart by other means.
This is working for 'onHover' event, using vue-chartjs / vue3 / compostion API:
const chart = ref(null) ;
....
....
onHover: (e) => {
if (chart.value === null)
return;
const thisChart = chart.value.chart;
const canvasPosition = getRelativePosition(e, thisChart);
const dataX = thisChart.scales.x.getValueForPixel(canvasPosition.x);
const dataY = thisChart.scales.y.getValueForPixel(canvasPosition.y);
console.log('x: ' + dataX + ' y: ' + dataY)
}
<template>
<Line
ref="chart"
:data = "chartData"
:options = "chartOptions"
/>
</template>
It's giving a typescript error for `chart.value.chart' because I cannot find the correct type definition for the chart isntance, but the code runs OK.
@quilkin
It's giving a typescript error for `chart.value.chart' because I cannot find the correct type definition for the chart isntance, but the code runs OK.
import { ChartComponentRef } from "vue-chartjs";
...
const chart = ref<ChartComponentRef | null>(null)
or if you need more strict typing based on the chart type:
const chart = ref<ChartComponentRef<"line"> | null>(null)
@Rednas83
I just started with migrating. from
vue-chart3
Is there also a composition example preferably in typescript?
For me the following works using @palsingh's workaround:
<script setup lang="ts">
import { nextTick, onMounted, ref } from "vue";
import { Line } from 'vue-chartjs'
import { ChartComponentRef } from "vue-chartjs";
const chart = ref<ChartComponentRef | null>(null)
onMounted(async () => {
await nextTick()
console.log(chart.value?.chart)
})
</script>
<template>
<Line ref="chart" :data="<data>" :options="<options>" />
</template>
@jeroenpelgrims
Thanks for suggestion - ChartComponentRef
solved that error but now getRelativePosition
is complaining:
Argument of type '{ readonly platform: { acquireContext: (canvas: HTMLCanvasElement, options?: CanvasRenderingContext2DSettings | undefined) => CanvasRenderingContext2D | null; ... 6 more ...; updateConfig: (config: ChartConfiguration<...> | ChartConfigurationCustomTypesPerDataset<...>) => void; }; ... 46 more ...; getContext: () => ...' is not assignable to parameter of type 'Chart'. Type 'null' is not assignable to type 'Chart'.ts(2345)
@jeroenpelgrims Just tried the solution but it doesn't seem to work anymore😢
Because I am getting the folowing runtime error
Only modified it a little by adding some data and options.
<script setup lang="ts">
import { nextTick, onMounted, ref } from "vue"
import { Line } from "vue-chartjs"
import type { ChartComponentRef } from "vue-chartjs"
const chart = ref<ChartComponentRef | null>(null)
const chartData = ref({
labels: ["January", "February", "March"],
datasets: [{ data: [40, 20, 12] }],
})
const chartOptions = ref({
responsive: true,
})
onMounted(async () => {
await nextTick()
console.log(chart.value?.chart)
})
</script>
<template>
<Line ref="chart" :data="chartData" :options="chartOptions" />
</template>
I am using the latest packages
------------------------------
- Operating System: Windows_NT
- Node Version: v20.10.0
- Nuxt Version: 3.10.1
- CLI Version: 3.10.0
- Nitro Version: 2.8.1
- Package Manager: pnpm@8.15.1
- Builder: -
- User Config: telemetry, vite, modules, build, routeRules, components, content, formkit, imports, css, devtools
- Runtime Modules: @vueuse/nuxt@10.7.2, normalizedModule(), @nuxt/content@2.12.0, @pinia/nuxt@0.5.1, @nuxtjs/tailwindcss@6.11.3, nuxt-icon@0.6.8, @formkit/nuxt@1.5.5
- Build Modules: -
------------------------------
Does anyone has a working solution for nuxt with the composition api?
Would you like to work on a fix?
Current and expected behavior
Can't get chart instance by ref. Chart ref value always return null
This is my code
Reproduction
https://stackblitz.com/edit/github-62t8lr?file=src/App.vue
chart.js version
^4.0.0
vue-chartjs version
^5.0.0
Possible solution
No response