Add dynamic data to Chart in LWC

Isha Arora
3 min readJun 2, 2020

--

For those who are new to Lightning web components also called LWC. Below mentioned links give a brief knowledge about them, their benefits, etc.

https://salesforce.stackexchange.com/questions/242469/what-are-lightning-web-components?rq=1

https://salesforce.stackexchange.com/questions/244594/why-lightning-web-component

Agenda : To give a brief background, we are using Chart.js library to render the Pie Chart dynamically using the Lightning web components.

There are some pre-requisites before setting up the Chart which are as follows:

1.Install Visual studio and setup with Salesforce DX

To start with Lightning Web Components, please use the following link from Salesforce Trailhead

https://trailhead.salesforce.com/en/content/learn/projects/quick-start-lightning-web-components

2. Download the latest version of chart.js and upload it in the static resource. There might be some problems with the latest Chartjs (2.9.3). It is not compatible with the LWC locker service according to the link below

https://salesforce.stackexchange.com/questions/260958/error-while-trying-to-build-a-chart-in-lwc

So, the most important note is to use the 2.7.3 version of Chartjs as your static resource. You can download from the below link :

https://cdn.jsdelivr.net/npm/chart.js@2.7.3/dist/Chart.js

Account object is being used and the data has been grouped based on the Rating field available on the Account, The number of Accounts with a particular rating is shown on the pie chart.

So, Let’s talk about the Apex Controller first. Below mentioned code is being used to get the Accounts that are grouped by Rating. The getAllAccountByRating function returns the count of Accounts for a particular rating. The data looks something like this:

count=3, label=” Hot”

@AuraEnabled(cacheable=true)public static List<DataSet> getAllAccountsByRating(){List<AggregateResult> result =  [Select Count(Id) cnt, Rating from Account  group by Rating limit 10];
List<DataSet> dataSet = new List<DataSet>();
for(AggregateResult ar:result){String status = (String)ar.get('Rating') ;
Integer total =(Integer)ar.get('cnt');
dataSet.add(new DataSet(status ,total));
}
System.debug('dataSet'+dataSet);
return dataSet ;
}
public class DataSetpublic DataSet(String label ,Integer count){this.label = label ;
this.count = count ;
}
@AuraEnabled
public String label {get;set;}
@AuraEnabled
public Integer count {get;set;}
}

The js file initializes the chart in the renderedcallback() which is followed by getting the data from apex using @wire and updating the chart’s dataset and labels.

import { LightningElement,wire,track} from 'lwc';//importing the Chart library from Static resources
import chartjs from '@salesforce/resourceUrl/ChartJs';
import { loadScript } from 'lightning/platformResourceLoader';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';
//importing the apex method.
import getAllAccountsByRating from '@salesforce/apex/AccountController.getAllAccountsByRating';
export default class FourthLwc extends LightningElement {@wire (getAllAccountsByRating) accounts({error,data})
{
if(data)
{
for(var key in data)
{
this.updateChart(data[key].count,data[key].label);
}
this.error=undefined;
}
else if(error)
{
this.error = error;
this.accounts = undefined;
}
}
chart;
chartjsInitialized = false;
config={
type : 'doughnut',
data :{
datasets :[
{
data: [
],
backgroundColor :[
'rgb(255,99,132)',
'rgb(255,159,64)',
'rgb(255,205,86)',
'rgb(75,192,192)',
],
label:'Dataset 1'
}
],
labels:[]
},
options: {
responsive : true,
legend : {
position :'right'
},
animation:{
animateScale: true,
animateRotate : true
}
}
};
renderedCallback()
{
if(this.chartjsInitialized)
{
return;
}
this.chartjsInitialized = true;
Promise.all([
loadScript(this,chartjs)
]).then(() =>{
const ctx = this.template.querySelector('canvas.donut')
.getContext('2d');
this.chart = new window.Chart(ctx, this.config);
})
.catch(error =>{
this.dispatchEvent(
new ShowToastEvent({
title : 'Error loading ChartJS',
message : error.message,
variant : 'error',
}),
);
});
}
updateChart(count,label)
{

this.chart.data.labels.push(label);
this.chart.data.datasets.forEach((dataset) => {
dataset.data.push(count);
});
this.chart.update();
}
}

The Html file looks something like this:

<template>
<lightning-card title='Sample Chart'>
<div>
<canvas class="donut" lwc:dom="manual"></canvas>
</div>
</lightning-card>
</template>

Chart.js manipulates the dom and in order for it to do so, we need to add the lwc:dom attribute.

So, This is it for now. Let me know in comments if this was helpful to you, Thank you! Any feedback or suggestions are welcome.

--

--