How to create one common angular ng2-charts (Bar chart) component which can be call from different components with different parameter

喜欢而已 提交于 2019-12-11 04:55:32

问题


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.


回答1:


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

ngOnInit() {
    this.barChartData = this.barchartservice.getBarChartData("one");
  }

One way would be to get barChartData outside of the component as Input 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 use Input to get data from outside of component.

You code will be like this:

bar-chart.component.ts

import { Component, OnInit, Input } 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 {
  @Input() barChartData: ChartDataSets[]; // <- note this line
  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]; 



  constructor(private barchartservice: BarChartService) {}

  ngOnInit() {}

  // 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;
  }
}

Now in your parent component you can get the parentChartData through your Service and then give it to your common component like this:

parent.component.html

<app-first-bar-chart [barChartData]="parentChartData"></app-first-bar-chart>

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 properties

import { Component, OnInit, Input } 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 {
  @Input() barChartData: ChartDataSets[]; // <- note this line
  @Input() labels: Label[];
  @Input() chartType: ChartType;

And your component tag would be like this:

<app-first-bar-chart [chartType]="'bar'" [labels]="myLabelsArray" [barChartData]="parentChartData"></app-first-bar-chart>


来源:https://stackoverflow.com/questions/56306678/how-to-create-one-common-angular-ng2-charts-bar-chart-component-which-can-be-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!