[英]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>
编辑
这是我编辑的打字稿代码。 每个图块都有一个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.