Search code examples
vuejs2chart.jsvue-chartjs

Trying to refresh label when click on it. Cannot read property '_meta' of undefined"


I'm trying that the percentages in a pie-chart refresh when clicking in a legend to hide data.

So far, I can display the chart with percentages, but they don't change if I hide one of the legends.

This is the chart: initial chart

This is how looks after the click: after click

We expect that instead 55.6%, it shows 100%.

This is my code so far:

 <script>
    import {Pie} from "vue-chartjs";
    import ChartJsPluginDataLabels from 'chartjs-plugin-datalabels';

    export default {
        extends: Pie,
        ChartJsPluginDataLabels,

        props: {
            data: Array,
            bg: Array,
            labels: Array
        },
        data() {
            return {

            }
        },
        computed: {
            chartData() {
                return this.data
            },
            bgData() {
                return this.bg
            },
            total() {
              return this.data.reduce((a, b) => a + (b || 0), 0)
            }
        },
        methods: {
            renderPieChart() {
                this.renderChart({
                    labels: this.labels,
                    datasets: [
                        {
                            label: "Data One",
                            backgroundColor: this.bgData,
                            data: this.chartData,
                            hoverBackgroundColor: "#f78733"
                        }
                    ]
                }, {
                    responsive: true,
                    plugins: {
                        datalabels: {
                            formatter: (value) => {
                                let sum = this
                                    .$refs.canvas.getContext('2d').dataset._meta[1].total; //use this.total to fix percentages
                                let percentage = (value * 100 / sum).toFixed(1) + "%";
                                return percentage;
                            },
                            color: '#fff'
                        }
                    }
                })
                console.log()

            },
            updateSelected(point, event) {
                const item = event[0]
                this.selected = {
                    index: item._index,
                    value: this
                        .chartData
                        .datasets[0]
                        .data[item._index]
                }
            }

        },
        watch: {
            bg: function () {

                this.renderPieChart();
            },
            data: function () {

                this.renderPieChart();
            }

        },
    }
</script>

Solution

  • In order to obtain the expected result, you should define plugins.datalabels.formatter as follows:

    formatter: (value, context) => {   
      return (value * 100 / context.dataset._meta[0].total).toFixed(1) + "%";
    }
    

    new Chart(document.getElementById("myChart"), {
      type: "pie",
      data: {
        labels: ['Savings', 'House'],
        datasets: [{
          label: "Data One",
          backgroundColor: ['#4e9258', '#64e986'],
          data: [9, 7],
          hoverBackgroundColor: "#f78733"
        }]
      },
      options: {
        plugins: {
          datalabels: {
            formatter: (value, context) => {   
              return (value * 100 / context.dataset._meta[0].total).toFixed(1) + "%";
            },
            color: '#fff'
          }
        }
      }
    });
    <script src="https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.bundle.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/chartjs-plugin-datalabels"></script>
    <canvas id="myChart" height="100"></canvas>