Pelegyair
Pelegyair

Reputation: 19

data is shown on chartjs-vue only after resizing browser or opening developer tools

im having hard time fixing this problem. i get my data with a get request, after opening developer tools or resizing browser the data is shown. i have tried some delay or timeout solutions but sadly could not make it work. i need the fastest solution, even if it is a "dirty hack" sort of solution. im using vue 2.9.1 and chartjs-vue 2.7.1. thank you! this is my code:

import {Line} from 'vue-chartjs'

export default { 
  name: 'Events', 
  extends: Line,
  created: function () {
    this.getEvents();
        },
  data () {
    return {
      gradient: null,
      gradient2: null,
      datesList : [],
      avgList: []
    }
  },
  methods:{

    graphClickEvent(event, array){
      var points = this.getElementAtEvent(event)
      },
       getEvents () {
            this.$http.get('http://localhost:8081/users/getAllEvents'
             ,{headers: {'Content-Type': 'application/json',
              'Authorization': localStorage.getItem('token'),}
            }).then((res) => {
              // res.body = array of event object
              var eventsArr = res.body;
                var arrayLength = eventsArr.length;
                for (var i = 0; i < arrayLength; i++) {
                  var date = new Date(parseInt(eventsArr[i].startTime))
                  var day = date.getDate()
                  var month =  date.getMonth()
                  var year = date.getFullYear()
                  var hours = date.getHours()
                  hours = ("0" + hours).slice(-2);
                  var minutes = date.getMinutes()
                  minutes = ("0" + minutes).slice(-2);
                  var str = day;
                  var str = day + "." + (month + 1) + "." + year +" - " + hours + ":" + minutes
                    this.datesList.push(str);
                }
                for (var i = 0; i < arrayLength; i++) {
                    var evnt = eventsArr[i];
                  this.avgList.push({label: evnt.name,y: evnt.pulseAverage ,tag: evnt.tag, id: evnt.id });
                }
            })
        }
  },
  mounted () {
    this.gradient = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)
    this.gradient2 = this.$refs.canvas.getContext('2d').createLinearGradient(0, 0, 0, 450)

    this.gradient.addColorStop(0, 'rgba(255, 0,0, 0.5)')
    this.gradient.addColorStop(0.5, 'rgba(255, 0, 0, 0.25)');
    this.gradient.addColorStop(1, 'rgba(255, 0, 0, 0)');
    
    this.gradient2.addColorStop(0, 'rgba(0, 231, 255, 0.9)')
    this.gradient2.addColorStop(0.5, 'rgba(0, 231, 255, 0.35)');
    this.gradient2.addColorStop(1, 'rgba(0, 231, 255, 0)');


    this.renderChart({
      labels: this.datesList,
      datasets: [
        {
          label: 'Events',
          borderColor: '#05CBE1',
          pointBackgroundColor: 'white',
          pointBorderColor: 'white',
          borderWidth: 2,
          backgroundColor: this.gradient2,
          data: this.avgList
         },
      ]
    ,
     options: {
        scales: {
            xAxes: [{
                ticks: {
                    beginAtZero:true
                }
            }]
        }
    }
  }
     
    //
     ,{ onClick: function(event){
      var activePoints = this.getElementAtEvent(event)
       var firstPoint = activePoints[0];
  if(firstPoint !== undefined){
    var label = this.data.labels[firstPoint._index];
    var value = this.data.datasets[firstPoint._datasetIndex].data[firstPoint._index];
    var location = "eventGraph?id=" + value.id;
    window.location.href = location;
    }
       }
      , responsive: true, maintainAspectRatio: false,fontColor: '#66226',
    tooltips: {
                enabled: true,
                mode: 'single',
                callbacks: {
                   title: function(tooltipItems, data) {
                    var evnt = data.datasets[0].data[tooltipItems[0].index].label;
                    return evnt
                  },
                    label: function(tooltipItems, data) { 
                       var avg = 'Average heart: ' + [tooltipItems.yLabel];
                       var evnt = 'Type: ' + data.datasets[0].data[tooltipItems.index].tag;
                        return [avg,evnt];
                    }
                }
            }
          })
}
}

Upvotes: 1

Views: 2784

Answers (1)

Russell Shingleton
Russell Shingleton

Reputation: 3196

It sounds like an initialization issue where the chart is initially rendered in an element that is not visible or it can't determine the size of the parent.

I see similar issues doing a Google:

One suggested doing a chart refresh when everything is visible:

setTimeout(function() { myChart.update(); },1000);

In think in vue this could be done in the mount function.

I'm sure there is a more elegant way to handle this with a watch function or something similar for instance.

Updated:

As mentioned in the comments, I've seen references to people firing a window resize event manually using:

window.dispatchEvent(new Event('resize'));

I think it would probably work in the mounted function of the vue component:

export default {
    name: 'graphs-component',
    mounted: function(){
         window.dispatchEvent(new Event('resize'));
    }
}

You might even wrap it in a setTimeout to ensure everything is loaded.

Upvotes: 4

Related Questions