vue3-apexcharts
vue3-apexcharts copied to clipboard
Options are not reactive!
I was expecting the options to be reactive. In the code example below, the startDate
and endDate
are related to the annotation in the options, but when clicking the button Process, which sets the new annotation, the chart does not re-render.
This is the example code:
<template>
<div class='row q-gutter-md'>
<q-input label='Start Date'
v-model='data.startDate' />
<q-input label='End Date'
v-model='data.endDate' />
<q-btn label='Process' @click='process' />
</div>
<apexchart width='900'
:options='options'
:series='series'
@dataPointSelection='onClick' />
</template>
<script lang='ts'>
import { defineComponent, reactive } from 'vue';
export default defineComponent({
name: 'ProgramTimeline',
setup() {
const portfolioWindowColor = '#c7b2d6';
const programColor = '#098489';
const phantomColor = '#86d0cc';
const data = reactive({
startDate: '2020-06-01',
endDate: '2021-06-01'
});
const series = [
{
name: 'Program 1',
data: [
{
x: 'Pool 1',
y: [
new Date('2019-01-01').getTime(),
new Date('2020-01-01').getTime()
],
meta: { id: 1 }
},
{
x: 'Pool 1',
y: [
new Date('2020-01-01').getTime(),
new Date('2021-01-01').getTime()
]
},
{
x: 'Pool 1',
y: [
new Date('2021-01-01').getTime(),
new Date('2022-01-01').getTime()
]
}
]
},
{
name: 'Program 2',
data: [
{
x: 'Pool 2',
y: [
new Date('2018-01-01').getTime(),
new Date('2019-01-01').getTime()
]
},
{
x: 'Pool 2',
y: [
new Date('2019-01-01').getTime(),
new Date('2020-01-01').getTime()
]
},
{
x: 'Pool 2',
y: [
new Date('2020-01-01').getTime(),
new Date('2021-01-01').getTime()
],
fillColor: phantomColor
}
]
},
{
name: 'Program 3',
data: [
{
x: 'Pool 3',
y: [
new Date('2018-06-01').getTime(),
new Date('2019-06-01').getTime()
]
},
{
x: 'Pool 3',
y: [
new Date('2019-06-01').getTime(),
new Date('2020-06-01').getTime()
]
}
]
}
];
const options = {
colors: [programColor],
chart: {
height: 450,
type: 'rangeBar',
dropShadow: {
enabled: false
}
},
tooltip: {
x: {
show: true,
format: 'dd MMM yyyy'
},
y: {
formatter: undefined,
title: {
formatter: (seriesName: any) => `${seriesName}`
}
}
},
annotations: newPortfolioWindow(data.startDate, data.endDate),
plotOptions: {
bar: {
horizontal: true,
barHeight: '25%',
rangeBarGroupRows: true
}
},
xaxis: {
type: 'datetime'
},
grid: {
xaxis: {
lines: {
show: true
}
}
},
stroke: {
width: 1.5,
colors: ['white']
},
fill: {
type: 'solid',
opacity: 0.6
},
legend: {
show: false
}
};
function newPortfolioWindow(start: string, end: string) {
const startDate = new Date(start).getTime();
const endDate = new Date(end).getTime();
return {
xaxis: [
{
x: startDate,
x2: endDate,
fillColor: portfolioWindowColor,
label: {
text: 'Portfolio window',
textAnchor: 'left',
position: 'top',
orientation: 'horizontal',
style: {
background: '#fff',
color: '#777'
}
}
}
]
};
}
function process() {
// This should re-render the chart, but it's not working.
options.annotations = newPortfolioWindow(data.startDate, data.endDate);
console.debug(options.annotations);
}
function onClick(event: any, chartContext: any, config: any) {
const { seriesIndex, dataPointIndex } = config;
const element = series[seriesIndex]['data'][dataPointIndex];
alert(JSON.stringify(element));
}
return { series, options, data, onClick, process };
}
});
</script>
These are the versions I'm using:
"apexcharts": "^3.28.1",
"vue3-apexcharts": "^1.4.1",
You can use updateOptions.
It is necessary to update all options for reactive to trigger update. What I found works is the following for example of dynamic options or data:
const darkModeActive= ref(false); // controlled elsewhere
const chartOptions = ref({
theme: {
mode: darkModeActive.value ? 'dark' : 'light',
},
xaxis: {
categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998]
}
});
// it was mentioned somewhere else that you must update the entire options from the root and just spread to your
// desire option to update
watch(darkModeActive, (newVal) => {
chartOptions.value = {
...chartOptions.value,
...{
theme: {
mode: newVal ? 'dark' : 'light',
},
}
}
});
// HTML
<apexchart
height="300"
type="line"
:options="chartOptions"
:series="series"
/>
Don't work with series: data are not reactiv
I was making an API call after which I needed to update the chart so I wrote a function
const updateChart = ()=>{ series.pop() series.push(30) }
It popped the last value from the array and pushed a new value which somehow started updating my chart.
I called this update method from my API response like this:
myStore.someMethod({ }).then(response => { updateChart() }).catch(error => { console.log(error) })
This way it started working, wasted hours in solving this, hope it helps someone.
It is necessary to update all options for reactive to trigger update. What I found works is the following for example of dynamic options or data:
const darkModeActive= ref(false); // controlled elsewhere const chartOptions = ref({ theme: { mode: darkModeActive.value ? 'dark' : 'light', }, xaxis: { categories: [1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998] } }); // it was mentioned somewhere else that you must update the entire options from the root and just spread to your // desire option to update watch(darkModeActive, (newVal) => { chartOptions.value = { ...chartOptions.value, ...{ theme: { mode: newVal ? 'dark' : 'light', }, } } }); // HTML <apexchart height="300" type="line" :options="chartOptions" :series="series" />
This worked for me, after hour and hours of debugging, thanks a lot.