Search code examples
vue.jschart.jsvue-chartjs

Line chart not rendering data


I'm not able to render the data inside my chart.

WaveChart.js:

import { Line, mixins } from "vue-chartjs";
const { reactiveProp } = mixins;
import { mapGetters } from "vuex";

export default {
  extends: Line,
  mixins: [reactiveProp],
  name: "WaveChart",
  props: ["options", "chartData"],
  computed: {
    ...mapGetters(["getZoom"])
  },
  mounted() {
    this.renderChart(this.chartData, this.options);
  },
  methods: {
    reRender() {
      this.renderChart(this.chartData, this.options);
    }
  },
  watch: {
    options: {
      deep: true,
      handler: "reRender"
    },
    getZoom() {
      this.reRender();
    }
  }
};

Wave.vue:

<template>
  <WaveChart
    id="line-chart"
    :chartData="chartData"
    :options="chartOptions"
    :styles="waveChartStyle"
  ></WaveChart>
</template>
<script>
import WaveChart from "@/components/editorComponentsWidgets/chart/WaveChart";
import { broadcasterHubProxy } from "@/services/signalr_connection";
export default {
  name: "Wave",
  components: {
    WaveChart
  },
computed: {
    ...mapGetters(["getShouldFetch", "getZoom"]),
    renderChartHeight() {
      return (this.chartHeight * this.getZoom) / 100;
    },
    waveChartStyle() {
      return {
        height: `${this.renderChartHeight}px`,
        width: "inherit",
        position: "relative"
      };
    },
    chartOptions() {
      return {
        lineWidth: 1,
        elements: {
          point: {
            radius: 0
          }
        },
        plugins: {
          datalabels: {
            display: false
          },

          filler: {
            propagate: true
          }
        },
        scales: {
          xAxes: [
            {
              ticks: {
                display: true
              },
              gridLines: {
                color: "rgba(0, 0, 0, 0)"
              }
            }
          ],
          yAxes: [
            {
              stacked: true,
              ticks: {
                callback: function(value) {
                  return value + "%";
                },
                min: this.minX,
                max: this.maxX,
                fontColor: this.labelColor,
                fontSize: this.labelFontSize
              },
              gridLines: {
                color: "rgba(0, 0, 0, 0)"
              }
            }
          ]
        },

        legend: { display: false },
        tooltips: {
          enabled: false
        },
        reactive: true,
        responsive: true,
        maintainAspectRatio: false
      };
    }
  },
  data() {
    return {
      render: true,
      chartData: {
        type: "line",
        labels: ["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"],
        datasets: [
          {
            label: "",
            backgroundColor: "",
            borderColor: "",
            data: []
          }
        ]
      }
    };
  },
}

And here's the function to create the chartData object:

updateWave(wave) {
      if (!wave) return;
      this.chartData.datasets.length = 0;
      wave.Categories.forEach(element => {
        var datasets = {
          label: element.Name,
          backgroundColor: `rgba(${element.R}, ${element.G}, ${element.B}, 1)`,
          borderColor: `rgba(${element.R}, ${element.G}, ${element.B}, 1)`,
          data: element.Values
        };
        this.chartData.datasets.push(datasets);
      });
    }

When I look at the props in WaveChart.js using Vue devtools I seem to have everything needed:

chartData:Object
    datasets:Array[12]
      0:Object
        backgroundColor:"rgba(0, 64, 128, 1)"
        borderColor:"rgba(0, 64, 128, 1)"
        data:Array[10]
        label:"Broken Edge"
      1:Object
      2:Object
      3:Object
      4:Object
      5:Object
      6:Object
      7:Object
      8:Object
      9:Object
      10:Object
      11:Object
labels:Array[10]
type:"line"
chartId:"line-chart"
cssClasses:""
height:400
options:Object
plugins:Array[0]
styles:Object
height:"282.6666666666667px"
position:"relative"
width:"inherit"
width:400

I really can't figure out why I cant see the datasets. Vue 2.6.11, chart.js 2.8.0, vue-chartjs 3.5.0.

UPDATE: I managed to render my datasets with async updateWave and adding a loaded value in data. Unfortunately it's not rerendering when I receive a new dto.


Solution

  • I fixed it by adding async to my function and a loading value:

    Wave.vue:

    <WaveChart
        v-if="loaded"
        id="line-chart"
        :chartData="chartData"
        :options="chartOptions"
        :styles="waveChartStyle"
    ></WaveChart>
    
    data() {
        return {
        loading: false
        }
    }
    
    methods: {
    async updateWave(wave) {
      if (!wave) return;
      this.chartData.datasets.length = 0;
      try {
        wave.Categories.forEach(element => {
          var datasets = {
            label: element.Name,
            backgroundColor: `rgba(${element.R}, ${element.G}, ${
              element.B
            }, 1)`,
            borderColor: `rgba(${element.R}, ${element.G}, ${element.B}, 1)`,
            data: element.Values
          };
          this.chartData.datasets.push(datasets);
        });
        this.loaded = true;
      } catch (e) {
        console.error(e);
      }
    }
    }
    

    And for updating I added a watcher in WaveChart.js:

    watch: {
        options: {
          deep: true,
          handler: "reRender"
        },
        chartData: {
          deep: true,
          handler: "reRender"
        },
      }