Cannot read property ‘labels’ of undefined

javascriptlightning-web-components

I'm trying to make these labels be dynamic:

enter image description here

But…

enter image description here

Here's what I tried:

chartExample.html

<template>
    <lightning-card title="Chart for Targets" icon-name="utility:chart">
        <div style="text-align: center;">
            <div>
                <canvas id="gaugechart" lwc:dom="manual"></canvas>
                <div id="percentage" style="font-size: 15px;"></div>
                <span id="gauge-value"></span>
            </div>
            <div if:false={isChartJsInitialized} class="slds-col--padded slds-size--1-of-1">
                Gauge Chart Not loaded yet
            </div>
        </div>
    </lightning-card>
</template>

chartExample.js

/* eslint-disable no-undef */
/* eslint-disable @lwc/lwc/no-api-reassignments */
/* eslint-disable @lwc/lwc/no-dupe-class-members */
import { LightningElement, track, api, wire } from "lwc";
import gaugechart from "@salesforce/resourceUrl/bernii_gauge";
import { loadScript } from "lightning/platformResourceLoader";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import getTarget from "@salesforce/apex/GaugeChartController.getTarget";
import { getRecord } from "lightning/uiRecordApi";

export default class ChartExample extends LightningElement {
  @track isChartJsInitialized = false;
  @track targetEvt;
  @api targetEvent = 0;
  @api error;
  @api recordId;
  chart;
  // targetDisplayValue;

  connectedCallback() {
    this.handleGetTarget();
  }

  @wire(getRecord, { recordId: "$recordId", fields: ["Event__c.Target__c"] })
  getTargetRecord({ data, error }) {
    if (data) {
      this.targetEvt = data.fields.Target__c.value;
      console.log(`targetEvt: ${this.targetEvt}`);
      // this.targetDisplayValue = data.fields.Target__c.displayValue;
      // console.log(this.targetDisplayValue)
      this.processRelatedObjetcs();
      this.loadChart();
    } else if (error) {
      console.error("ERROR => ", JSON.stringify(error));
    }
  }

  processRelatedObjetcs() {
    console.log(
      "processRelatedObjects for => ",
      JSON.stringify(this.targetEvt)
    );
  }

  handleGetTarget() {
    console.log(`recordId: ${this.recordId}`);
    getTarget({ eventId: this.recordId })
      .then((result) => {
        this.targetEvent = result.Target__c;
        this.error = undefined;
        this.loadChart();
      })
      .catch((error) => {
        this.targetEvent = undefined;
        this.error = error;
        console.log(error);
      });
  }

  config = {
    gradientType: 0,
    strokeColor: "#e0e0e0",
    generateGradient: true,
    pointer: {
      length: 0.5,
      strokeWidth: 0.05,
      iconScale: 1.0
    },
    // static labels
    staticLabels: {
      font: "15px sans-serif",
      labels: [0, 130000, 260000, 390000, this.targetEvt],
      fractionDigits: 0
    },
    // static zones
    staticZones: [
      { strokeStyle: "red", min: 0, max: 130000 },
      { strokeStyle: "orange", min: 130001, max: 260000 },
      { strokeStyle: "yellow", min: 260001, max: 390000 },
      { strokeStyle: "green", min: 390001, max: this.targetEvt }
    ],
    // the span of the gauge arc
    angle: 0,
    // line thickness
    lineWidth: 0.2,
    // radius scale
    radiusScale: 1,
    // font size
    fontSize: 40,
    // if false, max value increases automatically if value > maxValue
    limitMax: true,
    // if true, the min value of the gauge will be fixed
    limitMin: true,
    // High resolution support
    highDpiSupport: true
  };

  loadChart() {
    console.log("Método chamado");

    
    Promise.all([loadScript(this, gaugechart)])
    .then(() => {
        this.isChartJsInitialized = true;
        let target = this.template.querySelector("canvas");
        console.log(`let target: ${target}`);
        let gauge = new Gauge(target).setOptions(this.config);
        console.log(`gauge.maxValue: ${gauge.maxValue}`);
        gauge.maxValue = this.targetEvt;
        console.log(`gauge.maxValue: ${gauge.maxValue}`);
        gauge.setMinValue(0);
        gauge.animationSpeed = 32;
        gauge.set(8000);
        gauge.setTextField(this.template.querySelector("span"));
      })
      .catch((error) => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: "Error loading gauge.js",
            message: error.message,
            variant: "error"
          })
        );
      });
  }
}

enter image description here

Best Answer

in your wired method getTargetRecord you might want to ensure that data.fields.Target__c.value is not returning undefined.

there are several ways of doing this:

1.- undefined check using typeof

2.- Nullish coalescing operator (??)

3.- use Optional chaining (?.)

to ensure that when you load the chart loadChart those values are populated.

You can always opt to use a promise chain to ensure that you have the values you need when you reach the loadChart() method and invoke it imperatively at the end of your chain.

Related Topic