Forcetrails: How to use chartjs in Lightning Web Components

Hello There!!

Today, in the era of digital transformation, we believe in faster and reusable solutions. Open source is one of the best sources for this kind of solution. Here our problem is to build custom charts and graphs. To be able to build custom charts in Salesforce. We have two options from open source.

  1. D3.Js
  2. ChartJs
If you are looking for Bar Chart, here is the separate post.

Today we will see an example of using ChartJs in lightning web components.
Below are the steps for that.

  • Download the distributed version of ChartJs from here. (Open link -> Right Click -> Save As)
  • Upload the downloaded js file into the static resource with the name ChartJs
  • Create a new Lightning web component with name chartExample and put the following code into JS and HTML files respectively.

Here is the code for my component.

.js File

import { LightningElement, track } from 'lwc';
import chartjs from '@salesforce/resourceUrl/ChartJs';
import { loadScript } from 'lightning/platformResourceLoader';
import { ShowToastEvent } from 'lightning/platformShowToastEvent';


export default class ChartExample extends LightningElement {
    @track isChartJsInitialized;
    chart;

    config = {
        type: 'line',
        data: {
            datasets: [{
                fill: false,
                label: 'Line Dataset',
                data: [{  
                    y:100,
                    x:0
                 },
                 {  
                    y:96,
                    x:10
                 },
                 {  
                    y:93,
                    x:20
                 },
                 {  
                    y:89,
                    x:30
                 },
                 {  
                    y:85,
                    x:50
                 },
                 {  
                    y:80,
                    x:60
                 },
                 {  
                    y:71,
                    x:70
                 },
                 {  
                    y:43,
                    x:80
                 },
                 {  
                    y:19,
                    x:90
                 },
                 {  
                    y:9,
                    x:100
                 },
                 {  
                    y:4,
                    x:110
                 },
                 {  
                    y:2,
                    x:120
                 },
                 {  
                    y:0,
                    x:130
                 },
                 {  
                    y: 140,
                    x:140
                 }
                 
                 ],
                backgroundColor: [
                    'rgba(255, 99, 132, 0.2)'
                ],
                borderColor: [
                    'rgba(255, 99, 132, 1)'
                ],
                pointBackgroundColor: 'rgba(255, 99, 132, 0.2)',
                pointBorderColor: 'rgba(255, 99, 132, 1)'
            },
            {
                fill: false,
                label: 'Line Dataset 2',
                data: [{  
                    y:100,
                    x:0
                 },{  
                    y:98,
                    x:10
                 },{  
                    y:95,
                    x:20
                 },{  
                    y:92,
                    x:30
                 },{  
                    y:88,
                    x:50
                 },{  
                    y:84,
                    x:60
                 },{  
                    y:75,
                    x:70
                 },{  
                    y:50,
                    x:80
                 },{  
                    y:25,
                    x:90
                 },{  
                    y:14,
                    x:100
                 },{  
                    y:8,
                    x:110
                 },{  
                    y:5,
                    x:120
                 },{  
                    y:2,
                    x:130
                 }],
                backgroundColor: [
                    '#80aaff'
                ],
                borderColor: [
                    'blue'
                ],
                pointBackgroundColor: '#80aaff',
                pointBorderColor: 'blue'
            }
            ]
        },
        options: {
            title: {
                display: true,
                text: 'Sand Samples Against Comm Weight %.'
            },
            scales: {
                xAxes: [{
                    type: 'linear',
                    ticks: {
                        suggestedMin: 0,
                        suggestedMax: 140,
                        stepSize: 10
                    }
                }],
                yAxes: [{
                    type: 'linear',
                    ticks: {
                        autoSkip: true,
                        suggestedMin: 0,
                        suggestedMax: 100,
                        stepSize: 5,
                        callback: function (value) {
                            return value + '%';
                        }
                    }
                }]
            },
        }
    };

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

        Promise.all([
            loadScript(this, chartjs)
        ]).then(() => {
            const ctx = this.template.querySelector('canvas.linechart').getContext('2d');
            this.chart = new window.Chart(ctx, this.config);
            this.chart.canvas.parentNode.style.height = '100%';
            this.chart.canvas.parentNode.style.width = '100%';
        }).catch(error => {
            this.dispatchEvent(
                new ShowToastEvent({
                    title: 'Error loading ChartJS',
                    message: error.message,
                    variant: 'error',
                }),
            );
        });
    }
}

.html file

<template>
    <lightning-card title="Sand Samples" icon-name="utility:chart">
        <div class="slds-grid slds-wrap slds-grid--pull-padded">
            <div if:true={isChartJsInitialized} class="slds-col--padded slds-size--1-of-1">
                <canvas class="linechart" lwc:dom="manual"></canvas>
            </div>
            <div if:false={isChartJsInitialized} class="slds-col--padded slds-size--1-of-1">
                ChartJs Not loaded yet
            </div>
            <div class="slds-col--padded slds-size--1-of-1">
                Footer
            </div>
        </div>
    </lightning-card>
</template>


Now, add the below code to your meta-xml file after <apiVersion> tag to expose the component to the app builder, home page, or community page.

<isExposed>true</isExposed>
<targets>
    <target>lightning__AppPage</target>
    <target>lightning__RecordPage</target>
    <target>lightning__HomePage</target>
    <target>lightningCommunity__Page</target>
</targets>

This is the output.

Let me know in comments if this was helpful to you, thank you!
Happy Coding!!


You may also like...

26 comments:
  1. Build a config object for Chart
    Load the chart.


    Not getting these 2 steps. I deployed and I see no chart.

    ReplyDelete
    Replies
    1. You need to pass the configurations to chart, in that you can specify different properties of the chart, like data you want to load on chart, type of chart etc. For the demo purpose I have hardcoded this data on line 11 of js(search "config = {").

      Delete
    2. Hi Unknown User, I have modified that part of the post and I have added more details to avoid the confusion.

      Delete
  2. Will the chart rerender if i provide the dataset dynamically?

    ReplyDelete
    Replies
    1. Yes, Create another component and wrap this chart component inside it. Change 'config' into a public property using '@api'. Then pass the dynamic data from the parent component. I have some thing similar to this in my another post https://sftrailmixer.blogspot.com/2020/04/bar-chart-in-lightning-web-component-lwc-bar-chartjs.html on

      Delete
  3. i tried it out using exactly the same code you did, the chart is not displayed after being deployed. " ChartJs Not loaded yet" is not displayed either so the chart is just not rendering. what else should be checked?

    ReplyDelete
    Replies
    1. Did you upload the static resource, please check if the static resources are rendered correctly. Try putting log after this line "]).then(() => {".

      Also if you are looking for "How to feed dynamic data to the chart", then please my another post = https://sftrailmixer.blogspot.com/2020/04/bar-chart-in-lightning-web-component-lwc-bar-chartjs.html

      Delete
    2. I know why, there was problem in the code of loading the static resource I have fixed that. Now you can copy the updated code and use the same. Please let me know if further help is needed. Thanks!

      Delete
  4. Can we display reports and charts in lWC?

    ReplyDelete
    Replies
    1. Charts you can, but I am not sure about the standard Salesforce Reports, although you can create custom. Also, you can try adding the reports in an iframe, but I have never tried that.

      Delete
    2. I am doing an POC for displaying the reports in the LWC , where reports being generated from the objects in the salesforce so by grouping reports we can create an chart i want that chart tobe shown in LWC. i have looked for many source couldnt find an approach so far.

      Delete
    3. Is there any reason that you want to show standard reports in lwc? are you trying to display it in community?

      Delete
  5. we want to generate report on the existing data which has been there from many years and we are not displaying in community

    ReplyDelete
    Replies
    1. If you just need reports, I think you don't need LWC, just use the standard reports and dashboards.

      Delete
  6. I tried changing the chart type in config based on user selection. But chart loads and shows with old chart type only. Is there anyway we can achieve this?

    ReplyDelete
    Replies
    1. You need to update the chart whenever there is change in the data or configuration. You need to call the "chart.update()" method for this.

      Delete
    2. I tried it didnt work. And document also says it can only update data and options of chart.Can you provide correct syntax of doing it if possible?

      Delete
    3. I have done it like below. I have getter, setter to update the chart.

      @api
      get config() {
      return this._config;
      }

      set config(value) {
      console.log('inside set config!');
      this._config = value;

      if(this.chart){
      this.chart.update();
      this.isChartJsInitialized = false;
      console.log('chart updated');
      }
      }


      Also in the "renderedcallback" I have below code.


      renderedCallback() {
      if (this.isChartJsInitialized) {
      return;
      }
      this.isChartJsInitialized = true;
      if (this._config) {
      // because we cannot edit the public attribute passed by parent
      this.privateConfig = JSON.parse(JSON.stringify(this._config));
      Promise.all([
      loadScript(this, chartjs + '/dist/Chart.bundle.min.js')
      ]).then(() => {
      const ctx = this.template.querySelector('canvas.linechart').getContext('2d');
      this.chart = new window.Chart(ctx, this.privateConfig);
      //this.saveAsImage();
      }).catch(error => {
      this.dispatchEvent(
      new ShowToastEvent({
      title: 'Error loading ChartJS',
      message: error.message,
      variant: 'error',
      }),
      );
      });
      }
      }

      Delete
  7. Hi Rahul.. Do you have an example on Pie chart. If yes..plz share.
    Thanks

    ReplyDelete
    Replies
    1. Just use below configuration..

      config = {
      type: "pie",
      data: {
      datasets: [
      {
      data: [200, 450, 300, 50],
      backgroundColor: [
      "#ff6384",
      "#36a2eb",
      "#ffcd56",
      "#42d83f"
      ]
      }
      ],
      labels: ["Top", "High", "Low", "Volume"]
      }
      };

      Delete
  8. Hey!! Rahul,
    I am unable to see any thing in my chart,
    so when i did the console.log after this line "]).then(() => {".
    I found that there is error in inspect console of chorme, its not getting the correct url
    loadScript(this, chartjs + '/dist/Chart.bundle.min.js')--->what should i write in place of /dis.
    Thanks

    ReplyDelete
    Replies
    1. if you have uploaded the chartjs file directly.the just use loadScript(this, chartjs)

      Delete
  9. Hi Rahul, Can you provide example with D3.js chart

    ReplyDelete
  10. Can you provide example with D3.js chart.
    Thanks.

    ReplyDelete
    Replies
    1. Hello Mr/Ms None! I will upload the D3.js example very soon.

      Delete

Hi there, comments on this site are moderated, spams and promotions will be deleted. If you have any concern, or if you are not able to comment for some reason, reach email us at rahul@forcetrails.com