簡體   English   中英

Chart.js在同一組件中的Angular中創建多個圖表

[英]Chart.js creating multiple Charts in Angular in same Component

我有一個帶有組件的Angular 6項目,該組件獲取由其父級傳遞的tile對象。 對於每個平鋪密碼,我想使用chart.js生成相同的Chart。 我為第一個圖表工作良好,但其他所有圖表均未渲染。 控制台錯誤代碼: Failed to create chart: can't acquire context from the given item

我的tile.component.html

 <div *ngIf="tile.type === 'tileImg'"> <div class="card custom-card" routerLinkActive="glowing"> <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" /> <div class="card-body"> <p class=" card-text text-center">{{ tile.name }}</p> </div> </div> </div> <div *ngIf="tile.type === 'tileChart'"> <div class="card custom-card" routerLinkActive="glowing"> <div> <canvas id="canvas">{{ chart }}</canvas> </div> <div class="card-body"> <p class=" card-text text-center">{{ tile.name }}</p> </div> </div> </div> 

我的tile.component.ts-不要介意評論,僅用於測試目的

 import { Component, OnInit, Input } from '@angular/core'; import { Chart } from 'chart.js'; import { Tile } from 'src/app/tile-container/tile/tile.model'; //import { TileChart } from 'src/app/tile-container/tile/tile-chart.model'; @Component({ selector: 'app-tile', templateUrl: './tile.component.html', styleUrls: ['./tile.component.css'] }) export class TileComponent implements OnInit { @Input() tile: Tile; //tileChart: TileChart; chart = []; constructor() { } ngOnInit() { //console.log(this.tile); //console.log(this.tile.getType()); //console.log(this.tile.getChartType() + " " + this.tile.getChartData() + " " + this.tile.getType().localeCompare('tileChart')); //console.log(this.tile.getType() == 'tileChart'); if (this.tile.getType() == 'tileChart') { this.generateChart(this.tile.getChartType(), this.tile.getChartData()); } } generateChart(chartType: string, chartData: number[]) { this.chart = new Chart('canvas', { type: chartType, data: { datasets: [{ data: chartData, backgroundColor: ['#F39E01', '#b8bbc1'] }], labels: [ 'Verbrauch diese Woche', 'Einsparung in kWh' ] }, options: { legend: { display: false, }, rotation: 1.1 * Math.PI, circumference: 0.8 * Math.PI } }); } } 

還有父tile-container.component.html-並不是必須的

 <div class="container custom-container"> <div class="container-heading"> <h2>{{ tileContainer.name }}</h2> </div> <hr /> <div class="row"> <div class="col text-center" *ngFor="let tile of tileContainer.tiles"> <app-tile [tile]="tile"> </app-tile> </div> </div> </div> 

缺少圖表的Screnshot

編輯

這是我編輯的打字稿代碼。 每個圖塊都有一個ID,我嘗試使用該ID為創建的每個圖表都具有唯一的ID。

 ngOnInit() { console.log(this.tile.id); if (this.tile.getType() == 'tileChart') { this.chartId = this.tile.id.toString(); this.ctx = document.getElementById(this.chartId); console.log(this.ctx); this.generateChart(this.tile.getChartType(), this.tile.getChartData()); } } 

這是我使用數據綁定的html。

 <div> <p>{{ chartId }}</p> <canvas id="{{ chartId }}">{{ chart }}</canvas> </div> 

錯誤代碼的圖片

在模板(html)中,每個圖表的畫布ID必須不同

我將為您提供不同的方法,第一個是最簡單的,另一個則需要更多知識...希望對您有所幫助

1.-您可以生成一個僅用於呈現chartjs圖形的組件,例如,將其稱為帶有多個輸入id的chart-dynamic,以獲取呈現多個圖表所需的唯一ID,並為要渲染的所有完全對象提供dataChart,假設您的瓦。 組件看起來像這樣

重要!! 您的dataChart必須像一個對象數組一樣思考,每個對象基本上都是一個要呈現到模板中的圖表(遵循chartJs的正式文檔)

<div *ngIf="tile.type === 'tileImg'">
  <div class="card custom-card"
       routerLinkActive="glowing">
    <img class="card-img-top rounded" src="{{ tile.imgPath }}" alt="Tile image" />
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>
<div *ngIf="tile.type === 'tileChart'">
  <div class="card custom-card"
       routerLinkActive="glowing">
<!-- NEW CODE -->

<ng-container *ngIf="dataChart?.length > 0" >
<div *ngFor="let chart of dataChart; let i=index">
    <app-chart-dynamic [id]="SomeUniqueID" [dataChart]="chart" [type]="chart.type"></app-chart-dynamic>
</div>
</ng-container>

<!-- Finish here -->
    <div class="card-body">
      <p class=" card-text text-center">{{ tile.name }}</p>
    </div>
  </div>
</div>

在tile.component.ts中以對象數組的形式生成數據方法,將generateChart函數移至新組件中

import { Component, OnInit, Input } from '@angular/core';
import { Chart } from 'chart.js';

import { Tile } from 'src/app/tile-container/tile/tile.model';
//import { TileChart } from 'src/app/tile-container/tile/tile-chart.model';

@Component({
  selector: 'app-tile',
  templateUrl: './tile.component.html',
  styleUrls: ['./tile.component.css']
})
export class TileComponent implements OnInit {
  @Input() tile: Tile;
  //tileChart: TileChart;
  chart = [];
  public dataChart: [];

  constructor() { }

  ngOnInit() {
    //console.log(this.tile);
    //console.log(this.tile.getType());
    //console.log(this.tile.getChartType() + "   " + this.tile.getChartData() + "  " + this.tile.getType().localeCompare('tileChart'));
    //console.log(this.tile.getType() == 'tileChart');
    this.getCharts();
  }

  public getCharts() { 
    // call data from you service or data mock
    this.dataChart = {....response};
  }


}

現在假設您已經創建了新組件,則應該看起來像這樣(您已經導入了charJs和其他內容)

import { Component, OnInit, Input, ViewChild, ElementRef, AfterViewInit } from '@angular/core';
import { Chart } from 'chart.js';

@Component({
  selector: 'app-chart-dynamic',
  templateUrl: './chart-dynamic.component.html',
  styleUrls: ['./chart-dynamic.component.css']
})
export class ChartDynamic implements OnInit, AfterViewInit {

  @Input() datasChart: any;
  @Input() id: string;
  @Input() type?: string;
  public idChart: any;
  @ViewChild('chart') chart: ElementRef;
  public chartObject: any;

  constructor() { }

  ngOnInit() {

  }

  generateChart(id: string ,chartType?: string, chartData: any) {
    this.idChart = this.id;
    this.chart = new Chart(`${this.idChart}`,  this.datasChart );
  }

  ngAfterViewInit() {
    this.drawGraphics();
  }

}

應用圖表動態html文件

<div class="some-class-style" >
    <canvas [id]="id" #chart> {{ chart }}</canvas>
</div>

如果您添加到模塊等中,它應該可以工作

另一種方法是將viewChild和viewChildren與工廠解析器結合使用,這更復雜,但功能更強大,您應該根據角度文檔檢查點火

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM