0

I am using two child components inside a parent components these child component contains a Doughnut chart, and a Line chart. I have created label inside the doughnut chart using animation property of DoughnutChartOptions, but when I am switching between my child components through tabs in parent component my label inside doughnut chart disappears. below is the code please anyone has solution to this. The code in my doughnut charts component looks like this:

In ts:
import {
  Component,
  ElementRef,
  Input,
  NgZone,
  OnChanges,
  ViewChild,
} from "@angular/core";
import { Router } from "@angular/router";
import { ActiveElement, Chart, ChartConfiguration, ChartEvent } from "chart.js";
@Component({
  selector: "app-doughnut-chart",
  templateUrl: "./stats.component.html",
  styleUrls: ["./stats.component.scss"],
})
export class IndStatsComponent implements OnChanges {
  @Input("stats") stats: any;
  @ViewChild("myCanvas") canvas: ElementRef | any;
  public doughnutChartLabels: string[] = [];
  public doughnutChartDatasets: ChartConfiguration<"doughnut">["data"]["datasets"] =
    [{ data: [0, 0], label: " Files" }];
  public doughnutChartOptions: ChartConfiguration<"doughnut">["options"] = {
    responsive: true,
  };
  completedFiles: number = 0;
  incompleteFiles: number = 0;
  tabChanged: boolean = true;
  @Input() set isTabChanged(value: boolean) {
    if (value) {
      this.createLabel() // I tried to call every function but it didn't work
    }
 }
 
  constructor(private router: Router, private zone: NgZone) {}

  ngOnChanges(): void {
    if (this.stats === undefined) return;
    this.completedFiles = this.stats.complete.length;
    this.incompleteFiles = this.stats.incomplete.length;
    this.viewInit();
  }

  viewInit() {
    var me = this;
    // These line will create first gradient color for chart.
    let firstGradient = this.canvas.nativeElement
      .getContext("2d")
      .createLinearGradient(100, 100, 100, 200);
    firstGradient.addColorStop(0, "#68E4BC");
    firstGradient.addColorStop(1, "#11C6DB");
    // These line will create second gradient color for chart.
    let secondGradient = this.canvas.nativeElement
      .getContext("2d")
      .createLinearGradient(100, 100, 100, 200);
    secondGradient.addColorStop(0, "#4A99E8");
    secondGradient.addColorStop(1, "#0E3FC1");
    this.doughnutChartDatasets = [
      {
        data: [this.incompleteFiles, this.completedFiles],
        label: " Files",
        backgroundColor: [firstGradient, secondGradient],
        hoverBackgroundColor: [firstGradient, secondGradient],
        hoverBorderColor: [firstGradient, secondGradient],
        // borderWidth will add space between segments in chart.
        borderWidth: 6,
      },
    ];
    this.doughnutChartOptions = {
      responsive: true,
      plugins: {
        datalabels: {
          display: false,
        },
      },
      cutout: 55,
      animation: {
        onProgress: function () {
          me.createLabel();
        },
      },
      onClick: (
        event: ChartEvent,
        elements: ActiveElement[],
        chart: Chart<"bar">
      ) => {
        if (elements[0]) {
          this.zone.run(() => {
            this.router.navigate(["/toSomePage"]);
          });
        }
      },
    };
  }

  createLabel() {
    var ctx = this.canvas.nativeElement.getContext("2d");
    // the below lines will identify chart's height and width.
    var width = this.canvas.nativeElement.clientWidth,
    var height = this.canvas.nativeElement.clientHeight;

    // This below code will add first label in centre of chart.
    let fontSize = (height / 250).toFixed(2);
    ctx.font = 12 + "px Roboto";
    ctx.textBaseline = "middle";
    ctx.fillStyle = "Black";
    var text = "Total Files",
      textX = Math.round((width - ctx.measureText(text).width) / 2),
      textY = height - 100;
    ctx.fillText(text, textX, textY);

    // This below code will add second label in centre of the chart.
    let fontFamily = "Roboto";
    fontSize = (height / 150).toFixed(2);
    ctx.font = 30 + `px ${fontFamily}`;
    ctx.textBaseline = "middle";
    ctx.fillStyle = "Black";
    var text2 = this.completedFiles + this.incompleteFiles,
      text2X = Math.round((width - ctx.measureText(text2).width) / 2),
      text2Y = height - 70;
    ctx.fillText(text2, text2X, text2Y);
    ctx.restore();
  }
}
My HTML looks like this:
<div class="graph-container">
  <canvas
    #myCanvas
    baseChart
    [labels]="doughnutChartLabels"
    [datasets]="doughnutChartDatasets"
    [options]="doughnutChartOptions"
    [legend]="true"
    [type]="'doughnut'"
  >
  </canvas>
</div>
my parent component HTML looks like this:
<mat-tab-group
    mat-align-tabs="start"
    (selectedIndexChange)="this.index = $event"
    (selectedTabChange)="tabChanged($event)"
  >
    <mat-tab label="Stats"
      ><app-doughnut-chart [stats]="stats" [isTabChanged]="isTabChanged"></app-doughnut-chart>
    </mat-tab>
    <mat-tab label="Workflow"
      ><app-bar-char [workflow]="workflow"></app-bar-chart>
    </mat-tab>
  </mat-tab-group>
parent ts file:
import { Component, EventEmitter, OnInit, Output } from "@angular/core";
import { Router } from "@angular/router";
import { CommonService } from "src/app/services/common.service";

@Component({
  selector: "app-individual",
  templateUrl: "./individual.component.html",
})
export class IndividualComponent implements OnInit {
  @Output() widgetEvent: EventEmitter<any> = new EventEmitter();
  index: number = 0;
  stats: any;
  workflow: any;
  isTabChanged: boolean= false;
  constructor(private service: Service, private router: Router) {}

  ngOnInit(): void {
    this.getAndAssignChartData();
  }

  getAndAssignChartData() {
    this.service.Data().subscribe({
      next: (data: any) => {
        this.stats = data.stats;
        this.workflow = data.workflow;
      },
      error: (err) => {
      },
    });
  }

  tabChanged(event: any) {
    console.log("tab changed", event.index);
    if (event.index === 0) {
      this.isTabChanged = true
    } else {
      this.isTabChanged = false
    }
  }
}
Albina
  • 1,901
  • 3
  • 7
  • 19
Sanket
  • 1

0 Answers0