Angular中Chart.js嵌套数组实现可复用堆叠条形图报错排查
Angular 堆叠条形图组件报错排查
报错信息
开发基于@Input()传值的可复用ng2-charts堆叠条形图组件时,控制台抛出如下错误:
Error: Uncaught (in promise): TypeError: Cannot read property '0' of undefined
TypeError: Cannot read property '0' of undefined
复现代码
测试数据
barData = [[65, 59, 80, 81, 56, 55, 40], [28, 48, 40, 19, 86, 27, 90]]; barLabels = ["2006", "2007", "2008", "2009", "2010", "2011", "2012"];
原组件逻辑
@Input() barData!: (number | ScatterDataPoint | BubbleDataPoint)[][]; @Input() barLabels!: string[]; public barChartType: ChartType = "bar"; public barChartData: ChartConfiguration["data"]; defaultBarChartData: Partial<ChartConfiguration["data"]> = { labels: this.barLabels, datasets: [ { data: this.barData[0], label: "Income", backgroundColor: "#3ABD32" }, { data: this.barData[1], label: "Expense", backgroundColor: "#E02A45" }, ], }; ngOnInit(): void { if ( this.barData !== undefined && this.barLabels !== undefined && Array.isArray(this.barData) && this.barData.length > 0 && Array.isArray(this.barLabels) && this.barLabels.length > 0 ) { this.barChartData = { ...this.defaultBarChartData, ...{ labels: this.barLabels }, } as ChartConfiguration["data"]; this.barChartData.datasets[0].data = this.barData[0]; } else { throw new Error("Charts must have their data and labels inputs defined."); } } public barChartOptions: ChartConfiguration["options"] = {...}
原组件模板
<canvas baseChart [data]="barChartData" [options]="barChartOptions" [type]="barChartType"> </canvas>
错误根因
- 类属性初始化时机错误:
defaultBarChartData是类实例属性,在构造函数阶段就会执行初始化,此时@Input()装饰的属性还未完成绑定赋值,this.barData和this.barLabels均为undefined,直接读取this.barData[0]会触发类型错误,这是控制台报错的直接原因。 - 数据集赋值不完整:
ngOnInit中仅对第一个数据集datasets[0]的data做了重新赋值,第二个数据集datasets[1]的data始终是初始化阶段读取到的undefined值,会导致图表渲染异常。 - 缺少堆叠配置:原代码未在图表配置中开启x、y轴的堆叠属性,即便数据加载正确也无法实现堆叠条形图效果。
修复方案
- 移除提前初始化的
defaultBarChartData属性,所有图表数据组装逻辑放到ngOnInit生命周期中,待@Input()值完成绑定、且通过合法性校验后再构建完整的图表配置。 - 组装数据集时,同时给两个系列的data赋值,避免遗漏。
- 在图表options中开启x、y轴的stacked配置,实现堆叠效果。
- 如果父组件的barData、barLabels是异步接口返回的数据,需要在组件标签上加
*ngIf判断数据存在后再渲染组件,避免初始传空值触发校验错误。
修复后的组件逻辑代码如下:
import { Component, Input, OnInit } from '@angular/core'; import { ChartConfiguration, ChartType } from 'chart.js'; @Component({ selector: 'app-stacked-bar-chart', templateUrl: './stacked-bar-chart.component.html' }) export class StackedBarChartComponent implements OnInit { @Input() barData!: (number | ScatterDataPoint | BubbleDataPoint)[][]; @Input() barLabels!: string[]; public barChartType: ChartType = "bar"; public barChartData!: ChartConfiguration["data"]; // 补全堆叠必要配置 public barChartOptions: ChartConfiguration["options"] = { responsive: true, scales: { x: { stacked: true }, y: { stacked: true } } }; ngOnInit(): void { // 强化输入校验,要求barData至少包含2组数据 if ( !Array.isArray(this.barData) || this.barData.length < 2 || !Array.isArray(this.barLabels) || this.barLabels.length === 0 ) { throw new Error("Charts must have valid data and labels inputs, barData should contain at least 2 data groups."); } // Input值可用后再组装完整图表数据 this.barChartData = { labels: this.barLabels, datasets: [ { data: this.barData[0], label: "Income", backgroundColor: "#3ABD32" }, { data: this.barData[1], label: "Expense", backgroundColor: "#E02A45" } ] }; } }
模板部分无需修改即可正常渲染堆叠条形图。
内容的提问来源于stack exchange,提问作者Macy Narancs
相关产品推荐
相关产品推荐

