vue3-apexcharts icon indicating copy to clipboard operation
vue3-apexcharts copied to clipboard

Options are not reactive!

Open averri opened this issue 3 years ago • 5 comments

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",

averri avatar Sep 09 '21 11:09 averri

You can use updateOptions.

aitmamatovmusa avatar Oct 08 '21 11:10 aitmamatovmusa

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"
  />

cmcleese avatar Oct 28 '21 12:10 cmcleese

Don't work with series: data are not reactiv

UpsylonDev avatar May 05 '22 08:05 UpsylonDev

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.

kumarravisingh avatar Feb 17 '23 01:02 kumarravisingh

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.

CharlesChinedum avatar Mar 11 '24 06:03 CharlesChinedum