ng2-chart/chart.js Метка диаграммы Angular Donut исчезает, когда я переключаюсь между дочерними компонентами
Я использую два дочерних компонента внутри родительских компонентов, этот дочерний компонент содержитDoughnut
диаграмма иLine
диаграмма. Я создал метку внутри кольцевой диаграммы, используя свойство анимацииDoughnutChartOptions
, но когда я переключаюсь между дочерними компонентами через вкладки родительского компонента, моя метка внутри кольцевой диаграммы исчезает. ниже приведен код, пожалуйста, у кого-нибудь есть решение этой проблемы. Код в моем компоненте кольцевых диаграмм выглядит следующим образом:
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
}
}
}