Search code examples
vue.jsvue-chartjs

Rendering vuechart inside v-for


I'm reaching out to an API, saving the results in data, then using v-for to list out that data in a table. One of the columns includes a vuechart, but I can't seem to get it to display anything. If I inspect the component that is created it has data in the props array, but no dice on getting bars.

Is there something special about putting vuechart charts in v-for loops? Or am I not passing something correctly?

Here is the code:

TrendChart.js

import {Bar} from 'vue-chartjs'

export default {
  extends: Bar,
  name: 'TrendChart',
  props: ['data', 'options'],
  mounted() {
    this.renderChart(this.data, this.options)
  }
}

results.vue

<table>
  <tr v-for="result in results">
  ...
  <td>
    <trend-chart :data="result.trends", :options="{responsive: false, maintainAspectRatio: false}"></trend-chart>
  ...
</table>

If I inspect the component after it's rendered, I see that the props are there, but the data doesn't seem to be making it to the chart or so I assume, I have never seen a successful one yet (this is the output of Vue dev tools in text format):

props
  chartId:"bar-chart"
  cssClasses:""
  data:Array[12]
  height:400
  options:Object
  maintainAspectRatio:false
  responsive:false
  plugins:Array[0]
  styles:undefined
  width:400

data
  _chart:Unknown Component
  _plugins:Array[0]

Solution

  • Check Vue Chart Guide, the first parameter for this.renderChart() is one object instead one array.

    For example which is copied from above guide:

    {
      labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
      datasets: [
        {
          label: 'GitHub Commits',
          backgroundColor: '#f87979',
          data: [40, 20, 12, 39, 10, 40, 39, 80, 40, 20, 12, 11]
        }
      ]
    }
    

    Fix it then the charts should work fine.

    Below is one simple demo:

    Vue.config.productionTip = false
    let RawLineChart = window.VueChartJs.Bar
    Vue.component('line-chart', {
      extends: RawLineChart,
      props: ['data', 'options', 'name'],
      mounted () {
        this.renderChart({
          labels: ['January', 'February', 'March', 'April', 'May', 'June', 'July'],
          datasets: [
            {
              label: this.name,
              backgroundColor: '#f87979',
              data: this.data
            }
          ]
        }, this.options)
      }
    })
    
    new Vue({
      el: '#app',
      data() {
        return {
          results: [
            {name:'Chart A', trends: [40, 39, 20, 40, 39, 80, 40]},
            {name:'Chart B', trends: [140, 139, 110, 140, 139, 80, 140]},
            {name:'Chart C', trends: [240, 139, 210, 140, 239, 80, 240]}
          ]
        }
      }
    })
    <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.16/vue.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.1/Chart.min.js"></script>
    <script src="https://unpkg.com/vue-chartjs/dist/vue-chartjs.min.js"></script>
    <div id="app">
    <table>
      <tr v-for="result in results">
      <td>{{result.name}}</td>
      <td>
        <line-chart :data="result.trends" :name="result.name" :options="{responsive: false, maintainAspectRatio: false}">
        </line-chart>
        </td>
        </tr>
    </table>
    </div>