Issue with chart.js and vue

Posted 1 month ago by Gabotronix

Hi everybody, I'm trying to use chart.js with vue, so far results have been good but when I get my chart data via axios (data is not there when chart component is mounted) my chart doesn't display anything, I'm trying to come up with a method to rerender the charts when data in my component is actually there instead of waiting for the ajax call to complete but I haven't found a solution...

I pass all relevant data for my chart via props to my chart component, here is how it looks:

<template>
<section class="CHARTmaincontainer">
    <canvas :id="id" :width="width" :height="height"></canvas>
</section>
</template>
<!--SCRIPTS-->
<script>
import Chart from 'chart.js';
export default {
name: 'ChartJS',


props:
{
    id:{ required:true, type:String },
    type:{ default:'bar', type:String },
    width:{ default:400, type:Number},
    height:{ default:175, type:Number },
    data:{ required:true, type:Array },
    label:{ default:'Gráfico', type:String },
    labels:{ required: true, type:Array } 
},


mounted()
{
    let ctx = document.getElementById(this.id);
    let chart = new Chart(ctx, {
    type: this.type,
    data: {
        labels: this.labels,
        datasets: [{
            label: this.label,
            data: this.data,
            backgroundColor: [
                'rgba(255, 99, 132, 0.2)',
                'rgba(54, 162, 235, 0.2)',
                'rgba(255, 206, 86, 0.2)',
                'rgba(75, 192, 192, 0.2)',
                'rgba(153, 102, 255, 0.2)',
                'rgba(255, 159, 64, 0.2)'
            ],
            borderColor: [
                'rgba(255, 99, 132, 1)',
                'rgba(54, 162, 235, 1)',
                'rgba(255, 206, 86, 1)',
                'rgba(75, 192, 192, 1)',
                'rgba(153, 102, 255, 1)',
                'rgba(255, 159, 64, 1)'
            ],
            borderWidth: 1
        }]
    },
    options: {
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true
                },
                gridLines: {
                    display: true
                }
            }],
            xAxes: [{
                ticks: {
                    beginAtZero: true
                },
                gridLines: {
                    display: true
                }
            }]
        },
    },
    legend: {
        display: false
    },
    tooltips: {
        enabled: true,
        mode: 'single',
        callbacks: {
            label: function(tooltipItems, data) {
                return '$' + tooltipItems.yLabel;
            }
        }
    },
    responsive: true,
    maintainAspectRatio: false,
    });
},


};
</script>
<!--STYLES-->
<style scoped>
.CHARTmaincontainer{width:100%; display:flex; flex-direction:column; height:auto; margin:20px 0px;}
</style>

And here is the component where I place my chart components and where data is passed:

<template>
<section class="entry_maincontainer">
    <chart-js v-if="ordersCount"
        :id="'grafico1'"
        :data="ordersCount"
        :label="'Descuentos vendidos'"
        :labels="['Ene', 'Feb', 'Mar', 'Abr', 'May', 'Jun', 'Jul', 'Ago', 'Sep', 'Ago', 'Oct', 'Nov', 'Dic']">
    </chart-js>
</section>
</template>
<!--SCRIPTS-->
<script>
import { mapState, mapGetters, mapActions, mapMutations } from 'vuex';
export default {
name: 'StatsPanel',


computed:
{
    ...mapState('Orders', ['orders']),
    ...mapGetters('Orders', ['ordersCount', 'ordersTotal']),
    ...mapState('Globals', ['globals']),
    ...mapState('Loader', ['loader']),
},


mounted()
{
    console.log(this.$options.name+' component successfully mounted');
    this.getAll();
},


methods:
{
    ...mapActions('Orders', ['getAll']),
    ...mapMutations('Loader', ['RESET_LOADER']),
}


};
</script>
<!--STYLES-->
<style scoped>
</style>

My getter, this is the main data prop used to render my chart:

ordersCount: state => {

        let monthlyCount = { Enero:0, Febrero:0, Marzo:0, Abril:0, Mayo:0, Junio:0, Julio:0, Agosto:0, Septiembre:0, Octubre:0, Noviembre:0, Diciembre:0 };
        
        _.forEach(state.orders,  function(order) { 
            let capitalizedMonth = _.upperFirst(Vue.moment(order.created_at).format('MMMM'));
            monthlyCount[capitalizedMonth] = parseInt( monthlyCount[capitalizedMonth] ) + parseInt( order.discountcodes.length );
        });

        let values = Object.values(monthlyCount);

        return values;
    },

Please sign in or create an account to participate in this conversation.

Reply to

Use Markdown with GitHub-flavored code blocks.