I am trying to create a common ng2-charts (Bar Stacked) component, where I can pass the data from other component and it will get update. Actually, I want to display multiple same stacked bar charts with different values in the same page while loading the page.
I have created one common component with ng-2 charts and created one service also. Now I am calling the common component from one more different component via shared service with different parameter, but it is always showing first component value.
my first component (bar-chart.component.ts),
import { Component, OnInit } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { BarChartService } from "../service/bar-chart.service";
@Component({
selector: "app-bar-chart",
templateUrl: "./bar-chart.component.html",
styleUrls: ["./bar-chart.component.css"]
})
export class BarChartComponent implements OnInit {
public barChartOptions: ChartOptions = {
responsive: true,
// We use these empty structures as placeholders for dynamic theming.
scales: {
xAxes: [
{
stacked: true
}
],
yAxes: [
{
stacked: true
}
]
},
plugins: {
datalabels: {
anchor: "end",
align: "end"
}
}
};
public barChartLabels: Label[] = [
"2006",
"2007",
"2008",
"2009",
"2010",
"2011",
"2012"
];
public barChartType: ChartType = "bar";
public barChartLegend = true;
public barChartPlugins = [pluginDataLabels];
public barChartData: ChartDataSets[] = [];
constructor(private barchartservice: BarChartService) {}
ngOnInit() {
this.barChartData = this.barchartservice.getBarChartData("one");
}
// events
public chartClicked({
event,
active
}: {
event: MouseEvent;
active: {}[];
}): void {
console.log(event, active);
}
public chartHovered({
event,
active
}: {
event: MouseEvent;
active: {}[];
}): void {
console.log(event, active);
}
public randomize(): void {
// Only Change 3 values
const data = [
Math.round(Math.random() * 100),
59,
80,
Math.random() * 100,
56,
Math.random() * 100,
40
];
this.barChartData[0].data = data;
}
}
in the first bar-chart.component.html,
<div style="display: block">
<canvas
baseChart
[datasets]="barChartData"
[labels]="barChartLabels"
[options]="barChartOptions"
[plugins]="barChartPlugins"
[legend]="barChartLegend"
[chartType]="barChartType"
>
</canvas>
</div>
In the second-bar-chart.component.ts,
import { Component, OnInit } from "@angular/core";
import { ChartOptions, ChartType, ChartDataSets } from "chart.js";
import * as pluginDataLabels from "chartjs-plugin-datalabels";
import { Label } from "ng2-charts";
import { BarChartService } from "../service/bar-chart.service";
@Component({
selector: "app-second-bar-chart",
templateUrl: "./second-bar-chart.component.html",
styleUrls: ["./second-bar-chart.component.css"]
})
export class SecondBarChartComponent implements OnInit {
public barChartData: ChartDataSets[] = [];
constructor(private barchartservice: BarChartService) {}
ngOnInit() {
this.barChartData = this.barchartservice.getBarChartData("two");
}
}
in the, second-bar-chart.component.html,
<h3>This is 2nd Bar Chart</h3>
<app-bar-chart></app-bar-chart>
in the service (bar-chart.service.ts), I am writing like this,
import { Injectable } from "@angular/core";
@Injectable({
providedIn: "root"
})
export class BarChartService {
constructor() {}
getBarChartData(chartType) {
if (chartType == "one") {
return [
{ data: [65, 59, 80, 81, 56, 55, 40], label: "Series A", stack: "1" },
{ data: [28, 48, 40, 19, 86, 27, 90], label: "Series B", stack: "1" }
];
} else {
return [
{ data: [40, 59], label: "Male", stack: "1" },
{ data: [90, 48], label: "Female", stack: "1" }
];
}
}
}
I am expecting two different charts values but in both the component, it is showing only the first component chart value.
Please help me.
The problem with your code is the common component is not getting data from the parent component(2nd component) but it is getting its own data from the service using
One way would be to get
barChartData
outside of the component asInput
property. In this way every parent component will give the necessary data to your common component and the job of your common component will be to just display it. You can useInput
to get data from outside of component.You code will be like this:
bar-chart.component.ts
Now in your parent component you can get the
parentChartData
through yourService
and then give it to your common component like this:parent.component.html
In this way, you can use this component anywhere in your app and just provide it with the data(barChartData) and it will display it
Update
In order to make your
BarChartComponent
fully reusable. You can get the other attributes(labels
,chartType
etc) of your chart from the parent component.You code will include other
Input
propertiesAnd your component tag would be like this: