Как создать один общий угловой компонент ng2-charts (Bar chart), который можно вызывать из разных компонентов с разными параметрами - PullRequest
1 голос
/ 25 мая 2019

Я пытаюсь создать общий компонент 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;
  }
}

в первом bar-chart.component.html,

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

Во втором 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");
  }
}

в,second-bar-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" }
      ];
    }
  }
}

Я ожидаюдва разных значения диаграмм, но в обоих компонентах отображается только первое значение диаграммы компонентов.

Пожалуйста, помогите мне.

1 Ответ

0 голосов
/ 25 мая 2019

Проблема с вашим кодом в том, что общий компонент не получает данные от родительского компонента (2-й компонент), а получает свои собственные данные от службы, используя

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

Теперь в вашем родительском компоненте вы можете получить parentChartData через Service, а затем передать его общему компоненту, например:

parent.component.html

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

Таким образом, вы можете использовать этот компонент в любом месте вашего приложения и просто предоставить ему данные (barChartData), и он отобразит его

Обновление

Чтобы сделать ваш BarChartComponent полностью пригодным для повторного использования.Вы можете получить другие атрибуты (labels, chartType и т. Д.) Своей диаграммы из родительского компонента.

Ваш код будет включать в себя другие 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>
...