'ERROR TypeError: Cannot set properties of undefined (setting 'centralLabel')

I am using Angular Material 7 with Angular 7. For creating charts I am using angular-guage-chart: 0.7.2

I fetch some data from api, process it and then render the same as guage chart. However, this is not working fine me sometimes.

Sometimes, the chart doesn't get rendered and I get the following error:

at t.drawChart (main.976623a2e235b4123d4e.js:1:1482291)
at t.ngOnInit (main.976623a2e235b4123d4e.js:1:1481584)
at main.976623a2e235b4123d4e.js:1:380721
at main.976623a2e235b4123d4e.js:1:380764
at Ho (main.976623a2e235b4123d4e.js:1:382087)
at ha (main.976623a2e235b4123d4e.js:1:388580)
at Object.updateDirectives (11.676a246b04968a88821e.js:1:68006)
at Object.updateDirectives (main.976623a2e235b4123d4e.js:1:397512)
at No (main.976623a2e235b4123d4e.js:1:378668)
at Xo (main.976623a2e235b4123d4e.js:1:385605)

ERROR TypeError: Cannot read properties of undefined (reading 'removeGauge')
at t.drawChart (main.976623a2e235b4123d4e.js:1:1482252)
at t.ngDoCheck (main.976623a2e235b4123d4e.js:1:1482026)
at main.976623a2e235b4123d4e.js:1:380750
at main.976623a2e235b4123d4e.js:1:380764
at Ho (main.976623a2e235b4123d4e.js:1:382087)
at ha (main.976623a2e235b4123d4e.js:1:388580)
at Object.updateDirectives (11.676a246b04968a88821e.js:1:68006)
at Object.updateDirectives (main.976623a2e235b4123d4e.js:1:397512)
at No (main.976623a2e235b4123d4e.js:1:378668)
at Xo (main.976623a2e235b4123d4e.js:1:385605)

I am not sure why this is happening. Its not persistent behavior.

I found a similar issue on the repo here. However, it is marked as "closed" and fixed in version 0.5. I am using 2 versions higher the fix-applied version and still the problem.\

Strangely, when I a apply a delay of 1250 seconds or more, the issue never happens. This delay is between the data processing and the rendering of the chart.

Any advice here will be great help.

Below is the outline of my codebase (can't share entire code here because of my company policy)

ngOnInit() {
 
      this.getCultureDashboardData();
}

getCultureDashboardData() {
    clearInterval(this.timerID);
    this.loading = true;
    this.displayGaugeChart = false;

      this.chartApi
        .getCultureDashboardUpperPaneDataForBU(
          this.sharedService.month,
          this.sharedService.year,
          this.currentSelectedTag,
          this.currentSelectedTagValue
        )
        .subscribe(
          async (response) => {
            this.timerID = setInterval(() => {
              this.CultureData = response["culture_dashboard"];
              this.BusinessOutcomesArray = response["business_outcomes"];
              this.BusinessOutcomesDataArray = this.BusinessOutcomesArray.slice(
                0
              );
              this.CultureData.sort((a, b) => b.currentGM - a.currentGM);
              this.CultureDataArray = this.CultureData.slice(0);
  
              for (let i = 0; i < this.CultureData.length; i++) {
                if (
                  this.CultureData[i].name === "Sentiment Statement" ||
                  this.CultureData[i].name === "OVERRIDING SENTIMENT" || 
                  this.CultureData[i].name.includes("Overriding")
                ) {
                  this.CultureData.splice(i, 1);
                  break;
                }
              }

              for (let i = 0; i < this.CultureData.length; i++) {
                this.CultureData[i].id =
                  this.CultureData[i].id === null ? 0 : this.CultureData[i].id;
  
                this.CultureData[i].currentGM =
                  this.CultureData[i].currentGM === null
                    ? "0"
                    : this.CultureData[i].currentGM;
                this.CultureData[i].lastGM =
                  this.CultureData[i].lastGM === null
                    ? "0"
                    : this.CultureData[i].lastGM;
                this.CultureData[i].title =
                  this.CultureData[i].title === null
                    ? ""
                    : this.CultureData[i].title;
  
                this.CultureData[i].graphArray.title =
                  this.CultureData[i].graphArray.title === null
                    ? ""
                    : this.CultureData[i].graphArray.title;

///*******************Here I am passing the API data to setGaugeChartOption function. This function is responsible for creating object which the chart uses*****************//////

                this.setGaugeChartOption(this.CultureData[i]);


              }
              let counter = 1 + this.CultureData.length;
              this.noOfElement = this.CultureData.length;
              this.setDynamicWidth(counter);
              this.loading = false;
              this.displayGaugeChart = true;
            }, 1250);
            if(this.isNewDashboard == true)
              {
                await  this.getStrengthAndImprovement();
                await  this.getTopAndBottom()
                await  this.getAllComments();
              }
          },
          (error) => {
            console.log(error);
            this.loading = false;
          }
        );
}

setGaugeChartOption(object) {
    let value;
    if (
      object.name === this.dimensions[0] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[1] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[2] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[3] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[4] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[5] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    } else if (
      object.name === this.dimensions[6] &&
      object.name !== "OVERRIDING SENTIMENT" &&
      object.name !== "Sentiment Statement"
    ) {
      value = {
        hasNeedle: false,
        needleColor: "gray",
        needleUpdateSpeed: 1000,
        // arcColors: [this.getColor(object), '#e0e0e0'],
        arcColors: [this.getArcColour(object.currentGM), '#e0e0e0'],
        arcDelimiters: [this.getCurrentGM(object.currentGM)],
        rangeLabel: ["0", "100"],
        needleStartValue: 50,
        rangeLabelFontSize: 15,
      };
    }
    object.gaugeChartOptions = value;
}

//********And in the template, I am putting this inside ngFor:****///

<ng-container *ngFor="let cb1 of CultureData; let i = index">
          <div
            fxFlex
            fxLayout="column"
            [@fadeInOut]
            [ngStyle]="{ width: dynamicTileWidth1 }"
          >
            <div class="centre card-title" style="margin-bottom: 0 !important">
              {{ cb1.name | titlecase }}
            </div>
            <mat-card
              class="example-card cursor-class"
              matBadge="x"
              matBadgeColor="warn"
              (click)="navigateToDrillDown(cb1, i)"
              style="margin-bottom: 1rem; background: transparent"
              [ngStyle]="{ width: dynamicTileWidth2 + 'rem' }"
            >
              <div
                (click)="removeCardFromCultureData(cb1)"
                class="close-click"
              ></div>
              <div
                fxLayout="row"
                fxLayoutAlign="center space-between"
                style="width: 100%; height: 8.5rem"
              >
               
                <ng-container *ngIf="displayGaugeChart">
                  <rg-gauge-chart
                    [canvasWidth]="canvasWidth"
                    [needleValue]="65"
                    [centralLabel]="cb1.currentGM"
                    [options]="cb1?.gaugeChartOptions"
                    style="z-index: -1"
                  >
                  </rg-gauge-chart>
                </ng-container>

                
              </div>
              <div
                class="gauge-diff"
                fxLayout="row"
                fxLayoutAlign="center center"
                style="width: 100%"
              >
                <div class="diff-box">
                  <span class="old">{{ cb1.lastGM | titlecase }}</span>
                  <span
                    class="diff-result"
                    [ngClass]="{
                      'positive-result': cb1.currentGM - cb1.lastGM > 0,
                      'negative-result': cb1.currentGM - cb1.lastGM < 0,
                      'same-result': cb1.currentGM - cb1.lastGM == 0
                    }"
                  >
                    {{ getAbs(cb1.currentGM - cb1.lastGM) }}
                   
                    <i
                      class="fas fa-arrow-up"
                      *ngIf="cb1.currentGM - cb1.lastGM > 0"
                    ></i>
                    
                    <i
                      class="fas fa-arrow-down"
                      *ngIf="cb1.currentGM - cb1.lastGM < 0"
                    ></i>
                    <i
                      class="fas fa-arrows-alt-v"
                      *ngIf="cb1.currentGM - cb1.lastGM == 0"
                    ></i>
                  </span>
                  <span class="current">{{ cb1.currentGM }}</span>
                </div>
              </div>
              
            </mat-card>
          </div>
        </ng-container>


/// Sorry for gibberish formatting


Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source