Chart JS isn’t dynamically updating with new data with update() method

I’m using Chart JS with the Vue Chart JS wrapper inside of my Nuxt JS project. For some reason, despite new data my chart isn’t updating with new data. My charts are set up with a component named LineChart.vue, along with a plugin called LineChart.js inside of my plugins directory.

My component looks like:

<template>
  <div>
    <line-chart :chart-data="customChartData" class="data-chart"></line-chart>
  </div>
</template>

<style>
.data-chart canvas {
  width: 100% !important;
  height: auto !important;
}
</style>

<script>
import LineChart from '~/plugins/LineChart.js'
export default {
  components: {
    LineChart
  },
  props: {
    chartKey: {
      type: Number,
      default: 0
    },
    groupBy: {
      type: String,
      default: 'hourly'
    },
    labels: {
      type: Array,
      default: null
    },
    datasets: {
      type: Array,
      default: null
    },
    options: {
      type: Object,
      default: () => ({})
    }
  },
  data () {
    return {
      customChartData: {}
    }
  },
  mounted () {
    this.fillData()
  },
  methods: {

    /*
    ** Fill data
    */
    fillData () {

      const labelsToUse = []
      const labels = this.labels
      const first = labels[0]
      const last = labels[labels.length - 1]
      let diff = 0

      for (const [index, label] of labels.entries()) {
        const periodStart = this.$dayjs(Date.parse(first))
        const periodFinish = this.$dayjs(Date.parse(last))
        diff = periodFinish.diff(periodStart, 'day', true)

        if (!diff) {
          labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format('MMM Do'))
        }

        labelsToUse.push(this.$dayjs.tz(label, this.$auth.user.timezone).format(`${diff > 1 ? 'MMM Do' : 'HH:mm'}`))
      }

      this.customChartData = {
        labels: labelsToUse,
        datasets: this.datasets,
        options: this.options
      }
    }

  }
}
</script>

and my plugin looks like…

import { Line, mixins } from 'vue-chartjs'
import _ from 'lodash';
const { reactiveProp } = mixins

export default {
  extends: Line,
  mixins: [reactiveProp],
  data () {
    return {
      options: {
        responsive: true,
        maintainAspectRatio: false,
        legend: {
          display: false
        },
        scales: {
          yAxes: [{
            gridLines: {
              display: true,
              color: '#eceaea'
            },
          }],
          xAxes: [{
            gridLines: {
              display: false
            },
            ticks: {
              autoSkip: true,
              maxTicksLimit: window.innerWidth < 575 ? 2.1 : 4.1,
              maxRotation: 0,
              minRotation: 0
            }
          }]
        },
        elements: {
          point: {
            radius: 0,
            hitRadius: 35
          }
        }
      }
    }
  },
  mounted () {
    this.renderLineChart()
  },
  methods: {

    /*
    ** Get chart options
    */
    getChartOptions () {
      return this.options
    },

    /*
    ** Render a line chart
    */
    renderLineChart () {
      const options = this.getChartOptions()

      // this.chartdata is created in the mixin.
      // If you want to pass options please create a local options object
      this.renderChart(this.localData, options)
    }

  },
  computed: {
    localData: function() {
      return this.chartData
    }
  },
  watch: {
    chartData: {
      handler: function (val, oldVal) {
        const options = this.getChartOptions()
        const clone = _.cloneDeep(this.localData)

        console.log(this.localData)
        this._data._chart.update()
        this.renderChart(clone, options)
      },
      deep: true
    }
  }
}

When I log console.log(this.localData) inside of my watch method of my plugin, I’m not seeing my labels get updated with the new labels and data that are pushed from :labels="server[Object.keys(server)[0]].history.labels" inside of my webpage where I’m calling my line chart, what am I missing?

My page which called my chart component is:

<div class="col-span-12" v-for="(server, index) in servers" :key="index">
  <div class="bg-white p-6 rounded-md">
    <h3 class="text-md font-medium text-gray-900">{{ server[Object.keys(server)[0]].agent.agent }}</h3>
  </div>
  <hr v-if="server[Object.keys(server)[0]].history" />
  <div v-if="server[Object.keys(server)[0]].history" class="bg-white p-6 rounded-md">
    <h3 class="text-md font-medium text-gray-500 mb-3">Free memory</h3>
    <div class="chart chart--generic">
      <LineChart
        :labels="server[Object.keys(server)[0]].history.labels"
        :datasets="[{
          fill: false,
          borderWidth: 2.5,
          pointBackgroundColor: '#fff',
          borderColor: '#5046e5',
          data: server[Object.keys(server)[0]].history.data,
        }]"
      />
    </div>
  </div>
</div>

Answer

After updating the array labels, You could try to call your fillData() method.

Hope it works