1

Howdie!

I am trying to pass a value from a parent LWC to a child LWC and use that value in child LWC to draw a donut chart using Charts JS. Problem I am facing is that when I print the value passed from the parent, it prints fine but in my JS controller it is undefined and hence the chart doesn't render. What am I doing wrong? Below is a abstract of what I am trying to after taking away business logic. drawdata variable is what I am expecting to use to draw the chart

Parent LWC HTML

<template>
<c-poc-doughnut-chart drawdata={drawdata}></c-poc-doughnut-chart>
</template>

Parent LWC JS

import { LightningElement,track } from 'lwc';
export default class PocParentDashboard extends LightningElement {
    @track drawdata = [35,55];
}

Child LWC JS

import { LightningElement, api } from 'lwc';
import { loadScript, loadStyle } from 'lightning/platformResourceLoader';
import chartjs from '@salesforce/resourceUrl/Charts';


export default class PocDoughnutChart extends LightningElement {
   error;
   chart;
   chartjsInitialized = false;
   @api drawdata; //this is the value I am expecting from parent LWC

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

       Promise.all([
           loadScript(this, chartjs + '/Chart.min.js'),
           loadStyle(this, chartjs + '/Chart.min.css')
       ])
           .then(() => {
               //drawing the chart logic here
               // disable Chart.js CSS injection
               window.Chart.platform.disableCSSInjection = true;

               const canvas = document.createElement('canvas');
               this.template.querySelector('div.chart').appendChild(canvas);
               const ctx = canvas.getContext('2d');
               this.chart = new window.Chart(ctx, config = {
                type: 'doughnut',
                data: {
                    datasets: [
                        {
                            data: this.drawdata,//Using value from parent here
                            backgroundColor: [
                                'rgb(255, 99, 132)',
                                'rgb(75, 192, 192)'
                            ],
                            label: 'Demo'
                        }
                    ],
                    labels: ['Used', 'Remaining']
                },
                options: {
                    responsive: true,
                    legend: {
                        position: 'right'
                    },
                    animation: {
                        animateScale: true,
                        animateRotate: true
                    }
                }
            });
           })
           .catch((error) => {
               this.error = error;
           });
   }
}

LWC Child HTML

<template>
    <lightning-card title="Draw Chart" icon-name="custom:custom19">
        <div class="chart slds-m-around_medium" lwc:dom="manual"></div>
    </lightning-card>
</template>

1 Answer 1

2

It looks like there's a race condition, so I would fix this by adjusting your chart logic some:

_privateData;

@api set drawdata(value) {
  this._privateData = value;
  if(this.chartjsInitialized) {
    this.chartjsConfig.data.datasets[0].data = value;
    this.chart.update();
  }
}
get drawdata() {
  return this._privateData;
}
renderedCallback() {
  ...
  datasets: [ { data: this.privateData, ... }

This would also allow your code to be "reactive" to changes in the data automatically. See also Updating Chart Data, which is where I based this answer from. I have not tested this code, but hopefully it should get you close to your solution.

1
  • SFDCFOX to the rescue! Appreciate the response and yes I was able to get it working, should have read about the update function. Thanks mate!
    – PoopMan
    Jul 26, 2020 at 1:25

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .