[SalesForce] Not able to pass dynamic data into Chartjs in LWC

public with sharing class lwcLifetimeSpendingController {

  @AuraEnabled (cacheable=true)
  public static List<AggregateResult> getAccountLifetimeSpending(){
    return [SELECT SUM(Service_Amount__c) Service, SUM(Subscription_Booking__c) Subscription SUM(Renewal_Amount_Xactly__c) Renewal  FROM Opportunity WHERE AccountId = '0018000001G9dZUAAZ' and isClosed=true and isWon=true];
  }    
} //class

import { LightningElement,track,wire } from 'lwc';
import { getSObjectValue } from '@salesforce/apex';
import { loadScript } from 'lightning/platformResourceLoader';
import chartjs from '@salesforce/resourceUrl/chart';
import getAccountLifetimeSpending from '@salesforce/apex/lwcLifetimeSpendingController.getAccountLifetimeSpending';

const generateRandomNumber = () => {
    return Math.round(Math.random() * 100);
};


export default class LifetimeSpending extends LightningElement {        
@track lifetimeAggResult;
@track error;
serviceAmount;
subcriptionAmount;        

@wire(getAccountLifetimeSpending) lifetimeAggregateResult({error,data}) {
    if (data) {                         
        this.lifetimeAggResult = data;
        console.log('this.lifetimeAggResult: ' + this.lifetimeAggResult[0].Service);
        this.serviceAmount = this.lifetimeAggResult[0].Service;
        this.subcriptionAmount = this.lifetimeAggResult[0].Subscription;            
        this.error = undefined;
    } else if (error) {
        this.lifetimeAggResult = undefined;
        this.error = error;
        console.log('Error: ' + this.error);
    }        
}
chart;
chartjsInitialized = false;

config = {
    //type: 'doughnut',        
    type: 'bar',
    data: {                        
        datasets: [
            {                    
                data: [
                    this.serviceAmount,
                    this.subcriptionAmount
                ],
                backgroundColor: [
                    'rgb(255, 99, 132)',
                    'rgb(255, 159, 64)',
                    'rgb(255, 205, 86)',
                    'rgb(75, 192, 192)',
                    'rgb(54, 162, 235)'
                ],
                label: 'Dataset 1'
            }
        ],
        labels: ['Service', 'Subscription', 'Private Training', 'Public Training', 'Renewal']
    },
    options: {
        responsive: true,
        legend: {
            position: 'right'
        },
        animation: {
            animateScale: true,
            animateRotate: true
        }
    }
};

renderedCallback() {
    if (this.chartjsInitialized) {
        return;
    }
    this.chartjsInitialized = true;

    loadScript(this, chartjs)
        .then(() => {                
            const ctx = this.template
                .querySelector('canvas.donut')
                .getContext('2d');
            this.chart = new window.Chart(ctx, this.config);
        })
        .catch(error => {
            this.error = error;
        });
}
} //end export

<template>
    <lightning-card title="Lifetime Spending" icon-name="custom:custom19">
        <div class="slds-m-around_medium">
            <canvas class="donut" lwc:dom="manual"></canvas>
        </div>
        <template if:true={error}>
            <c-error-panel errors={error}></c-error-panel>
        </template>    
    </lightning-card>
</template>

The first code sample is a simple apex class lwcLifetimeSpendingController return List

The second code sample is LWC JS file.

The third code sample is the HTML file.

When I use data: [this.serviceAmount, this.subscriptionAmount] in the chart's data config, this.serviceAmount and this.subscriptionAmount do not return any data. The chart is just blank.

What can I do differently do render dynamic data from variables in the JS file?

Best Answer

Fetching data is asynchronous. It’s nearly always the case that connectedCallback is invoked prior to @wire provisioning a value.

This means you’re configuring the chart with no data. Data then arrives but you don’t pass it to the chart.

Checkout https://www.chartjs.org/docs/latest/developers/updates.html for how to update an existing ChartJS instance with new data. You need to do something comparable in lifetimeAggregateResult()

Related Topic