Search code examples
vue.jsvuejs2chart.jsvue-chartjs

How to get fixed legend and tooltip for dynamically generated data vue-chartjs


I'm trying to generate a vue chart with vuechartjs which would be number 10,20,30,40,50 repeated over a period of time (years).

I'm having hard time getting the legend and tooltip to work as expected.Currently, the label just prints out array of label, and tooltip showing respective labels.

Expected label legend:

Label 1, Label 2, Label 3, Label 4, Label 5 with respective colors: #F44336, #FC9900, #FCC106, #8BC34A, #4CAF50.

  1. How do I get legend with this label and colors?
  2. How do I get tool tip showing the label with the data point rather than each labels with the data point?
  3. How would one add an image to the tooltip / label?

Vue.component('reactive', {
	extends: VueChartJs.Bar,
	mixins: [VueChartJs.mixins.reactiveProp],
	data: function () {
		return {
			options: {
				scales: {
					yAxes: [{
						ticks: {
							beginAtZero: true
						},
						gridLines: {
							display: true
						}
					}],
					xAxes: [{
						ticks: {
							beginAtZero: true
						},
						gridLines: {
							display: false
						}
					}]
				},
				legend: {
					display: true
				},
				tooltips: {
					enabled: true,
					mode: 'single',
					callbacks: {
						label: function(tooltipItems, data) {
							return '$' + tooltipItems.yLabel;
						}
					}
				},
				responsive: true,
				maintainAspectRatio: false,
				height: 200
			}
		}
	},
	mounted () {
		// this.chartData is created in the mixin
		this.renderChart(this.chartData, this.options)
	}
})

var vm = new Vue({ 
	el: '.app',
	data () {
		return {
    	datacollection: null
    }
	},
	created () {
		this.fillData()
	},
	methods: {
		fillData () {
        this.datacollection = {
          labels: ['January 2010', 'February 2010', 'March', 'April', 'May 2011', 'June 2018', 'July', 'August 2011', 'August', 'October', 'November', 'December 2018'],
          datasets: [
            {
              label: ['Label 1', 'Label 2', 'Label 3', 'Label 4', 'Label 5'], 
              backgroundColor: this.getBackground(),
              data: [this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt(), this.getRandomInt()]
            }
          ]
        }
      },
    getRandomInt () {
			var myArray = [10,20,30,40,50]
			return myArray[Math.floor(Math.random()*myArray.length)];
         
      },
		getBackground() {
			return ["#8BC34A", "#4CAF50", "#4CAF50", "#4CAF50", "#4CAF50", "#4CAF50", "#F44336", "#FC9900", "#FCC106", "#8BC34A", "#8BC34A", "#4CAF50"]
		},
		
	}
})
<script src="https://unpkg.com/vue@2.5.17/dist/vue.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.7.3/Chart.min.js"></script>
<script src="https://unpkg.com/vue-chartjs@3.4.0/dist/vue-chartjs.js"></script>


<div class="app">
	<h1>Bar Chart</h1>
	<reactive :chart-data="datacollection"></reactive>
	<button class="button is-primary" @click="fillData()">Randomize</button>
</div>

Codepen


Solution

  • Well it prints out an array of labels, because you pass in for one dataset multiple labels.

    If you want a label for each datapoint, you need to pass multiple datasets. The labels, in most charts in chart.js define your X-Axis. For example dates.

    Then you define a dataset with a label. Which can have multiple datapoints. For example, "Usage of Javascript". In your data array you then have the matching data for the x-axis. If your labels have three values (jan, feb, ma) then your datasets[0].data[] should also have three values. The first would be matching for "Jan", the second for "Feb" etc.

    But thats only one dataset. And only one label for it. So only one entry in the legend. If you want mulitple entries, you need to define multiple datasets.

    labels: ['Jan', 'Feb', 'Mar'],
    datasets: [
      {
       label: ['Usage of Javascript'], 
       backgroundColor: this.getBackground(),
       data: [10, 20, 22]
      },
      {
       label: ['Usage of PHP'], 
       backgroundColor: this.getBackground(),
       data: [16, 18, 20]
      }
     ]