brianmsantos
brianmsantos

Reputation: 67

Am I using chart.update() correctly when trying to update the chart?

I have a chart created using chartjs and vuechartjs in my Vue project. Data will be passed in via mapGetters from my database. Data will change and the yAxes needs to be updated so that the ticks min and max and stepSize need to change corresponding to the available data being displayed. I wouldn't want my max to be 2500 with a step size of 250 when only displaying max data of 555. I want it to be closer to max 600 with stepSize of 50.

I read the documentation and it says to use chart.update(). I am trying to test this and it says that update cannot be read.

Error in v-on handler: "TypeError: Cannot read property 'update' of undefined"

Here is my code.

export default {
    components: {
      BarChart,
      RoiCalculator
    },
    data() {
      return {
        data: [0,0,0,0,0,0,0,0,0,0,0],
        maxFeedback: 0,
        datacollection: null,
        // Configure chart options here
        options: {
          tooltips: { 
            //Allows positioning of the tooltip to the event(mouse) position. Custom is the name of the position 
            //because that is the function created for Chart.Tooltip.positoners
            position : 'custom',    
            callbacks: {
              label: function(tooltipItem, data) {
               var label = Math.floor(tooltipItem.yLabel*100)/100+" "+data.datasets[tooltipItem.datasetIndex].label;
               return label;
              }
            }
          },
          maintainAspectRatio: false,  
          legend: {
            //Hides the legend that would normally say NPS scores
            display: false
          },
          // X and Y axes modified here
          scales: {
             // Allows you to customize the X axis
              xAxes: [{
                display: true,
                scaleLabel: {
                display: true,
                labelString: 'Rating',
                },
                gridLines: {
                  display: false,
                  tickMarkLength: 0,
                },
                ticks: {
                    padding: 15,
                    showLabelBackdrop: false
                }
              }],
              // Allows you to customize the Y axis
              yAxes: [{
                gridLines: {
                    tickMarkLength: 0,
                },
                ticks: {
                    padding: 15,
                    max: 500,
                    min: 0,
                    stepSize: 50
                },
              }]
          },
        },
      }
    },
    mounted() {
      this.populateFeedback();

    },
    computed: {

      ...mapGetters({
          filteredFeedback: "initialFeedback"
      }),
    tid: function() {
      return Spark.state.currentTeam.id;
      } ,
    },
    watch: {
      filteredFeedback: {
        handler(){
          this.loadData()
          this.getMaxData()
          this.resizeChart()
        },
      }, 
    }, 
    methods: {
         ...mapActions({
      changeInitialFeedback: "changeInitialFeedback",
    }),
    updateChart(chart){
      this.datacollection.datasets[0].data = [100, 200, 400, 600, 700, 1000, 120, 300, 305, 400, 555];
      this.chartData.update();
    },

    loadData(){
        this.datacollection = {
          labels: ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '10'],
          datasets: [{
            label: '',
            data: this.sortData(),
            backgroundColor: [
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(242, 74, 99)',
              'rgb(253, 205, 61)',
              'rgb(253, 205, 61)',
              'rgb(9, 198, 117)',
              'rgb(9, 198, 117)',
            ],
          }]
        }
      },
      resizeChart(){
        console.log(this.Chart)
        console.log(this.options.scales.yAxes[0].ticks.stepSize,'options')
        if(!this.maxFeedback <= 0 && !this.maxFeedback >=100){
          this.options.scales.yAxes[0].ticks.max = 100
          this.options.scales.yAxes[0].ticks.stepSize = 10
          }
        else if (this.maxFeedback <= 500){
          this.options.scales.yAxes[0].ticks.max = 500
          this.options.scales.yAxes[0].ticks.stepSize = 50
          }
        else (this.maxFeedback <= 2200)
          this.options.scales.yAxes[0].ticks.max = 2500
          this.options.scales.yAxes[0].ticks.stepSize = 250
      },
      getMaxData(){
        const maxFB = Math.max.apply(Math, this.datacollection.datasets[0].data)
        console.log(maxFB, 'hello')
        this.maxFeedback = maxFB
      },
      sortData(){
        //Filters through all our filtered feedback data and adds them to each rating
        const output=[0,0,0,0,0,0,0,0,0,0,0]
        this.filteredFeedback.forEach(function (e) {
          output[e.nps_rating] += 1
            }
          );
          return output
        },
      populateFeedback() {
      axios
      .get(`/api/metricsPage/all/` + this.tid)
      .then(response => {
        // Filtering out incomplete data
        let filteredFeedback = response.data.feedbacks.filter(feedback => {
          return feedback.nps_icon || feedback.has_comments;
        });
        filteredFeedback = filteredFeedback.map(feedback =>{
          feedback.service_rating = Number(feedback.service_rating);
          feedback.product_rating = Number(feedback.product_rating);
          feedback.delivery_rating = Number(feedback.delivery_rating);
          feedback.nps_rating = Number(feedback.nps_rating);
          return feedback;
        })
        // vuex calls to set global state
        this.changeInitialFeedback({ initialFeedback: filteredFeedback });
      })
      .catch(error => {
        throw error;

      });
  },
  }
}
</script>
<script>

// This file is what exports the chart used in the index
// Imports and determines type of chart (Line, Bar, etc.)
import { Bar } from 'vue-chartjs'
//Creates custom positioning for the positoning of the tooltip.  
Chart.Tooltip.positioners.custom = function(elements, eventPosition) { //<-- custom is now the new option for the tooltip position
    /** @type {Chart.Tooltip} */
    var tooltip = this;

    /* ... */

    return {
        x: eventPosition.x,
        y: eventPosition.y
    };
}
export default {
  extends: Bar, 
  props: ['options', 'chartData'],
  data() {
    return{
      chart: this.chartData
    } 
  },
  watch: {
  //Renders the chart 
    chartData(){
      this.renderChart(this.chartData, this.options)
    }
  },
}

</script>

I was expecting chart.update() to update but it keeps returning undefined.

Upvotes: 0

Views: 745

Answers (1)

Tyler Schroeder
Tyler Schroeder

Reputation: 730

The first component you posted refers to this.chartData(), however there is no chartData property on that component. You can force an update by create a ref, then accessing this.$refs.<yourref>.update() within your update handler.

Upvotes: 1

Related Questions