11

How can I update the data from the series for an ApexCharts I have created the following Vue Component using the ApexCharts. This component gets updated from the parent where a bunch of these components are situated. The updated values are coming in through props.

<template>
  <div>
    <apexchart type="line" width="1000px" :options="options" :series="series"></apexchart>
  </div>
</template>

<script>
import Vue from 'vue';
import VueApexCharts from 'vue-apexcharts';

Vue.use(VueApexCharts);
Vue.component('apexchart', VueApexCharts);

export default {
  name: 'EnergyConsumption',
  props: {
    channel1: Number,
    channel2: Number,
  },
  data() {
    return {
      options: {
        chart: {
          id: 'vuechart-example',
        },
        xaxis: {
          categories: ['Channel 1', 'Channel 2'],
        },
      },
      series: [
        {
          name: 'series-1',
          data: [this.channel1, this.channel2],
        },
      ],
    };
  },
  methods: {
    updateSeries() {
      this.series[0].data = [this.channel1, this.channel2];
    },
  },
  watch: {
    channel1: function (_channel1) {
      this.updateSeries();
      //   this.series[0].data[0] = _channel1;
    },
  },
};
</script>

With the Vue DevTools I can see that the data is changing inside the ApexCharts component, but the view is not updated.

If I take a look in the ApexCharts documentation, I see there is a method to update the series

updateSeries (newSeries, animate)

But I need an instance to call the updateSeries from. If I use the template mechanism, I can't have a reference to that module.

What is the best way to solve this issue?

Gander
  • 1,854
  • 1
  • 23
  • 30
Bik Lander
  • 192
  • 1
  • 2
  • 10

5 Answers5

21

You need to use ref for updating series.

<template>
  <apexchart
      ref="realtimeChart"
      type="line"
      height="200"
      :options="chartOptions"
      :series="series"
  />
</template>

<script>
export default {
  data() {
    return {
      series: [{
        name: 'Desktops',
        data: [10, 41, 35, 51, 49, 62, 69, 91, 99],
      }],
      chartOptions: {
        colors: ['#FCCF31', '#17ead9', '#f02fc2'],
        chart: {
          height: 350,
        },
        grid: {
          show: true,
          strokeDashArray: 0,
          xaxis: {
            lines: {
              show: true,
            },
          },
        },
        stroke: {
          curve: 'straight',
          width: 5,
        },
        // grid: {
        //   padding: {
        //     left: 0,
        //     right: 0,
        //   },
        // },
        dropShadow: {
          enabled: true,
          opacity: 0.3,
          blur: 5,
          left: -7,
          top: 22,
        },
        dataLabels: {
          enabled: false,
        },
        title: {
          text: 'Line',
          align: 'left',
          style: {
            color: '#FFF',
          },
        },
        xaxis: {
          categories: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep'],
          labels: {
            style: {
              colors: '#fff',
            },
          },
        },
        yaxis: {
          labels: {
            style: {
              color: '#fff',
            },
          },
        },
      },
    };
  },
  mounted() {
    this.setDataLineChart();
  },
  methods: {
    getRandomArbitrary(min, max) {
      return Math.floor(Math.random() * 99);
    },
    setDataLineChart() {
      setInterval(() => {
        this.series[0].data.splice(0, 1);
        this.series[0].data.push(this.getRandomArbitrary(0, 99));
        this.updateSeriesLine();
      }, 3000);
    },
    updateSeriesLine() {
      this.$refs.realtimeChart.updateSeries([{
        data: this.series[0].data,
      }], false, true);
    },
  },
};
</script>
Gander
  • 1,854
  • 1
  • 23
  • 30
Pratik Patel
  • 5,995
  • 1
  • 18
  • 39
8

If you are using VUE the chart updates automatically when you update the series.

Check the documentation:

Vue ApexCharts - How do I update the chart

There is no need to call updateSeries()

btowers
  • 109
  • 1
  • 7
5

I lived same problem, this can be easily corrected like this:

 updateChart() {
    this.series = [{ data: [100, 155, 200]}]
}

This is a clear example of how to update option or series in VueApexCharts:

https://codesandbox.io/s/qzjkzmzxoj?file=/src/components/Chart.component.vue:1307-1312

the documentation mentions it in this part:

Important: While updating the options, make sure to update the outermost property even when you need to update the nested property.

✅ Do this

    this.chartOptions = {
      ...this.chartOptions,
      ...{
        xaxis: {
            labels: {
            style: {
              colors: ["red"],
            },
          },
        },
      },
    };
sergioriverafl
  • 129
  • 2
  • 6
2

Well, I had the same problem just moments ago. You have to create a method that makes changes where you want and it will render automatically, but if you still have the same problem, check the documentation "vu-apexcharts" it will help you a lot, I'm using composition api and i solve this problem putting the ref value to the chart series and options. IE: This is my chart config

const series = ref([{
  data: [],
}, {
  data: [],
},
])
const chartOptions = ref({
  chart: {
    type: 'bar',
    height: 430,
  },
  colors:['#12fa62', '#cb0000'],
  plotOptions: {
    bar: {
      horizontal: true,
      dataLabels: {
        position: 'top',
      },
    }
  },
  dataLabels: {
    enabled: true,
    offsetX: -6,
    style: {
      fontSize: '12px',
      colors: ['#fff']
    }
  },
  fill: {
    colors: ['#12fa62', '#cb0000']
  },
  stroke: {
    show: true,
    width: 1,
    colors: ['#fff']
  },
  tooltip: {
    shared: true,
    intersect: false
  },
  xaxis: {
    categories: ['Hoho', 2002, 2003, 2004, 2005, 2006, 2007],
  },
})

I got this object

const closedContracts = ref({
  won: {
      title: 'closed and success',
      clients: [],
      total: 0,
  },
  losed: {
      clients: [],
      total: 0,
  }
})
And then i got my values from my db:

    const store = useStore()
    const updateChart = () => {
      series.value[0].data = closedContracts.value.won.clients.map(amm => amm.monto)
      series.value[1].data = closedContracts.value.losed.clients.map(amm => amm.monto)
    }
    onMounted(async() => { 
        await store.dispatch('actionGetChartsValues', closedContracts.value)
        updateChart()
        console.log(series.value) // prints my object's values
    })
Dharman
  • 30,962
  • 25
  • 85
  • 135
0

I think it doesn't have to be that difficult to achieve this goal. I would recommend the following steps to get your data dynamically from any external place:

  1. Create a state variable in vuex store and set the default value to an empty array
  2. Fetch the data from an API or database inside a vuex action and commit this to the state
  3. Call the action in the mount lifecycle hook of the component
  4. Map the state of the store to a computed property in the component
  5. Now, when the store is updated, the computed property is updated as well
  6. Your chart will automatically re-render, which is a built-in feature of Apex charts

Below is a small code example:

<ApexChart :options="options" :series="series"></ApexChart>

computed: {
  ...mapState(["results"]),
  series() {
    return [
      {
        data: this.$store.state.results.map((result: any) => result.score)
      }
    ]
  }
},
async mounted() {
  await this.$store.dispatch("getResults")
}

Note: the results array contains objects, which can be used to create a corresponding table for example. For series, we only need one numerical field (i.e. score) inside the objects, hence the map function.

Cloudkollektiv
  • 11,852
  • 3
  • 44
  • 71