【问题标题】:Can't pass array to chart.js which got its data from @Input无法将数组传递给从 @Input 获取数据的 chart.js
【发布时间】:2019-10-27 00:24:21
【问题描述】:

我正在尝试了解如何将数据从父组件传递到子组件。
更具体地说,我想将父组件的数组移交给子组件,以便将其用作图表的数据源。

我正在使用Angular 8mdbootstrap(它使用chart.js 2.5.0)。我阅读了一堆教程,并弄清楚了如何将内容从父组件传递到子组件。我可以使用外推法从我的子模板中访问字符串等。
我的问题可能与 chart.js 处理其图表呈现的方式有关。
我不确定它在生命周期的哪个阶段需要它的数据。我尝试在ngOnInit 方法和AfterViewInit 方法(代码中未显示)中填充所需的变量,但这并没有改变任何东西。

父组件(statistics.component.ts)

export class StatisticsComponent implements OnInit {

  // business logic
  public isDataLoaded = false;
  public clientNumberList: string[] = new Array();
  public clientNumberCountList: number[] = new Array();

  // chart related stufff
  public chartLabel = 'User Statistics';

  public chartOptions: any = {
    responsive: true,
    maintainAspectRatio: false,
    scales: {
      xAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Client Number'
        }
      }],
      yAxes: [{
        scaleLabel: {
          display: true,
          labelString: 'Count'
        }
      }]
    }
  };

  constructor(private sdoUserStatisticsService: SdoUserStatisticsService) {}

  ngOnInit(): void {
    // get users and counts
    this.sdoUserStatisticsService.getUserStatistics().subscribe(users => {
      for (const user of users) {
        this.clientNumberList.push(user.clientNumber);
        this.clientNumberCountList.push(user.count);
      }
      this.isDataLoaded = true;
    })
      ;
  }
}

statistics.component.html

<div *ngIf="isDataLoaded">
<app-bar-chart [chartLabelInput]="chartLabel" [dataArrayInput]="clientNumberCountList" [labelArray]="clientNumberList" [chartOptionsInput]="chartOptions"></app-bar-chart>
</div>

子组件(bar-chart.component.ts)

export class BarChartComponent implements OnInit{

  public chartType = 'bar';

  @Input() chartLabelInput: string;
  @Input() dataArrayInput: number[];

  public chartLabel: string;
  public dataArray: number[] = this.dataArrayInput;
  public chartDatasets: Array<any> = [
    {data: this.dataArray, label: this.chartLabel}
  ];

  @Input() labelArray: string[];
  public chartLabels: Array<any> = this.labelArray;

  @Input() chartOptionsInput: any;
  public chartOptions = this.chartOptionsInput;

  constructor() {}
  public chartClicked(e: any): void { }
  public chartHovered(e: any): void { }

  ngOnInit(): void {}
}

条形图.component.html

<canvas mdbChart
        [chartType]="chartType"
        [datasets]= "chartDatasets"
        [labels]="chartLabels"
        [options]="chartOptions"
        [legend]=true
        (chartHover)=chartHovered($event)
        (chartClick)=chartClicked($event)>
</canvas>

我希望我可以访问 bar-chart.component.ts 中的 dataArrayInput,从而将这些数据提供给图表。 实际上,我可以在 ngOnInit 方法(代码中未显示)中访问此数组,但不能将其用于图表。 我在浏览器控制台中收到以下错误:

ERROR TypeError: "newElm.data is undefined"
    Angular 10
        datasets
        getDatasets
        getChartBuilder
        refresh
        ngOnInit
        checkAndUpdateDirectiveInline
        checkAndUpdateNodeInline
        checkAndUpdateNode
        debugCheckAndUpdateNode
        debugCheckDirectivesFn
    View_BarChartComponent_0 BarChartComponent.html:1
    Angular 30
    RxJS 5
    Angular 9ERROR TypeError: "newElm.data is undefined"
    Angular 10
        datasets
        getDatasets
        getChartBuilder
        refresh
        ngOnInit
        checkAndUpdateDirectiveInline
        checkAndUpdateNodeInline
        checkAndUpdateNode
        debugCheckAndUpdateNode
        debugCheckDirectivesFn
    View_BarChartComponent_0 BarChartComponent.html:1
    Angular 30
    RxJS 5
    Angular 9

我希望有人可以帮助我:)

【问题讨论】:

  • @BenRacicot 我在发布我的问题之前阅读了那个问答。它帮助我理解了这个问题。但是chart.js 部分的问题仍然存在。
  • 知道了,在发送到任何地方之前,父级中的数组看起来是否正确?为了双方的利益,我会在 StackBlitz 中复制这一点。
  • 是的,如果我将父组件和子组件中的数组内容打印到控制台,它们是相同的。好的,我将尝试在 stackblitz 中复制问题
  • 好的,所以您可能想要更改问题的标题,使其不是重复问题,并且可能更具体到 chart.js 和 Angular。嘿,newElm 是什么?这不在你的代码中,问题就在那里。

标签: angular chart.js mdbootstrap


【解决方案1】:

我认为这是一个 Angular 生命周期问题。您的问题在于您如何使用 @Input 数据。您显然想要获取 dataArrayInput 传入的数据,但您没有正确访问它。

将依赖于@Input 值的变量分配移动到ngOnInit 方法中。 @Input 变量的值在组件构建期间不可用,因此当您创建因变量时,您将使用 undefined 对其进行初始化。

export class BarChartComponent implements OnInit {

  public chartType = 'bar';

  @Input() chartLabelInput: string;
  @Input() dataArrayInput: number[];

  public chartLabel: string;
  public dataArray: number[];
  public chartDatasets: Array < any > ;

  @Input() labelArray: string[];
  public chartLabels: Array < any > ;

  @Input() chartOptionsInput: any;
  public chartOptions;

  constructor() {}
  public chartClicked(e: any): void {}
  public chartHovered(e: any): void {}

  ngOnInit(): void {
    this.dataArray = this.dataArrayInput;
    this.chartDatasets = [{
      data: this.dataArray,
      label: this.chartLabel
    }];
    this.chartLabels = this.labelArray;
    this.chartOptions = this.chartOptionsInput;
  }
}

看看这个question和这个question

【讨论】:

  • 太棒了!这消除了有关未定义字段的错误!谢谢!现在我的问题是:图表选项变量的类型是 Object。我无法访问它的内容。我必须用它做点什么吗?
  • 您应该能够...我看到您在statistics.component.ts 中声明了它,因此它不会出现语法无效。做chartOptions.responsive 或whaterver 应该很简单。也许这是chart.js的配置问题?身份证
  • 好的,我想通了。我不得不将&lt;app-bar-chart&gt; 周围的div 移动到子模板。非常感谢您的帮助!
猜你喜欢
  • 2022-06-15
  • 1970-01-01
  • 2023-03-31
  • 1970-01-01
  • 2016-01-10
  • 2016-02-27
  • 1970-01-01
  • 2019-06-30
  • 2019-01-13
相关资源
最近更新 更多