如何创建一个通用的 angular ng2-charts(条形图)组件,可以从具有不同参数的不同组件调用

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

我正在尝试创建一个通用的 ng2-charts (Bar Stacked) 组件,我可以在其中传递来自其他组件的数据,并且它会得到更新。 实际上,我想在加载页面时在同一页面中显示多个具有不同值的相同堆叠条形图。

我用 ng-2 图表创建了一个通用组件,还创建了一项服务。现在我通过具有不同参数的共享服务从另一个不同的组件调用公共组件,但它总是显示第一个组件值。

我的第一个组件 (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;
  }
}

在第一个小节中-chart.component.html,

 <div style="display: block">
          <canvas
            baseChart
            [datasets]="barChartData"
            [labels]="barChartLabels"
            [options]="barChartOptions"
            [plugins]="barChartPlugins"
            [legend]="barChartLegend"
            [chartType]="barChartType"
          >
          </canvas>
        </div>

在第二栏-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");
  }
}

中,第二栏-chart.component.html,

<h3>This is 2nd Bar Chart</h3>
<app-bar-chart></app-bar-chart>

服务中(bar-chart.service.ts),我是这样写的,

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" }
      ];
    }
  }
}

我期待两个不同的图表值,但在两个组件中,它只显示第一个组件图表值。

请帮帮我。

您的代码的问题是公共组件没有从父组件(第二个组件)获取数据,而是使用

从服务获取自己的数据
ngOnInit() {
    this.barChartData = this.barchartservice.getBarChartData("one");
  }

一种方法是在组件外部获取 barChartData 作为 Input 属性。通过这种方式,每个父组件都会向您的公共组件提供必要的数据,而您的公共组件的工作就是显示它。 您可以使用 Input 从组件外部获取数据。

你的代码将是这样的:

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

现在,在您的父组件中,您可以通过 Service 获取 parentChartData,然后像这样将其提供给您的通用组件:

parent.component.html

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

通过这种方式,您可以在应用程序的任何地方使用这个组件,只需向它提供数据 (barChartData),它就会显示它

更新

为了使您的 BarChartComponent 完全可重用。您可以从父组件获取图表的其他属性(labelschartType 等)。

您的代码将包含其他 Input 属性

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;

你的组件标签应该是这样的:

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