ng2-charts更新标签和数据

mus*_*918 20 javascript chart.js ng2-charts angular

我正在尝试使用ng2-chart动态创建图表,我从角度2服务获取信息,当我仅更改图表的标签时它工作,当我更改数据时它只能工作,但当我更改两者时,只更新数据在图表中.对这种奇怪的行为有任何解释.

我的模板:

<canvas baseChart height="130" width="180"  
    [data]="doughnutChartData"
    [labels]="doughnutChartLabels"
    [chartType]="doughnutChartType"
    (chartHover)="chartHovered($event)"
    (chartClick)="chartClicked($event)">
</canvas>
Run Code Online (Sandbox Code Playgroud)

我的课 :

export class PlDoughnutComponent implements OnInit {

  constructor(private homeService: TileServiceService) { }

  ngOnInit() {
    this.updatePLdoughnut();

  }

  public util : UtilService = new UtilService();
  public doughnutChartLabels:string[] = ['Download Sales'];
  public doughnutChartData:number[] = [0,0,100];
  public doughnutChartType:string = 'doughnut';

  public updatePLdoughnut(){

    this.homeService.getTile().
    then(res => {

      this.doughnutChartLabels =  res.PLtypes;
      this.doughnutChartData = this.util.objectToIntArray(res.PLByTypes);

    })
  }
}
Run Code Online (Sandbox Code Playgroud)

Sle*_*er9 42

显然,如果你不修改标签数组的原始引用,它似乎工作,至少对我来说.我的意思是,如果你想要一套完全不同的标签,你应该这样做:

在模板中:

<canvas baseChart
  [datasets]="lineChartData"
  [labels]="lineChartLabels"
  [options]="lineChartOptions"
  [chartType]="'line'"></canvas>
Run Code Online (Sandbox Code Playgroud)

在ts组件中:

this.lineChartLabels.length = 0;
for (let i = tempLabels.length - 1; i >= 0; i--) {
  this.lineChartLabels.push(tempLabels[i]);
}
Run Code Online (Sandbox Code Playgroud)

或者,使用新的ECMAScript语法:

this.lineChartLabels.length = 0;
this.lineChartLabels.push(...tempLabels);
Run Code Online (Sandbox Code Playgroud)

关键可能是this.lineChartLabels.length = 0;语句,它通过将其长度设置为0来实际"清空"数组,而无需修改引用.希望这可以帮助!

  • 这个答案对我有用 (2认同)

小智 13

最近我不得不使用ng2-charts,我在更新数据时遇到了很大的问题,直到我发现这个解决方案:

<div class="chart">
    <canvas baseChart [datasets]="datasets_lines" [labels]="labels_line" [colors]="chartColors" [options]="options" [chartType]="lineChartType">
    </canvas>
</div>
Run Code Online (Sandbox Code Playgroud)

在这里我的组件:

import { Component, OnInit, Pipe, ViewChild, ElementRef } from '@angular/core';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';

@Component({
    moduleId: module.id,
    selector: 'product-detail',
    templateUrl: 'product-detail.component.html'
})

export class ProductDetailComponent {
    @ViewChild(BaseChartDirective) chart: BaseChartDirective;

    private datasets_lines: { label: string, backgroundColor: string, borderColor: string, data: Array<any> }[] = [
        {
        label: "Quantities",
        data: Array<any>()
    }
];

private labels_line = Array<any>();

private options = {
    scales: {
        yAxes: [{
            ticks: {
                beginAtZero: true
            }
        }]
    }
};


constructor() { }
ngOnInit() {

    this.getStats();

}
getStats() {

    this._statsService.getStatistics(this.startDate, this.endDate, 'comparaison')
        .subscribe(
        res => {
            console.log('getStats success');
            this.stats = res;

            this.labels_line = this.getDates();
            this.datasets_lines = [];

            let arr: any[];
            arr = [];
            for (let stat of this.stats) {
                arr.push(stat.quantity);
            }

            this.datasets_lines.push({
                label: 'title',
                data: arr
            });

            this.refresh_chart();

        },
        err => {
            console.log("getStats failed from component");
        },
        () => {
            console.log('getStats finished');
        });
}

refresh_chart() {
    setTimeout(() => {
        console.log(this.datasets_lines_copy);
        console.log(this.datasets_lines);
        if (this.chart && this.chart.chart && this.chart.chart.config) {
            this.chart.chart.config.data.labels = this.labels_line;
            this.chart.chart.config.data.datasets = this.datasets_lines;
            this.chart.chart.update();
        }
    });
}

getDates() {
    let dateArray: string[] = [];
    let currentDate: Date = new Date();
    currentDate.setTime(this.startDate.getTime());
    let pushed: string;
    for (let i = 1; i < this.daysNum; i++) {
        pushed = currentDate == null ? '' : this._datePipe.transform(currentDate, 'dd/MM/yyyy');
        dateArray.push(pushed);
        currentDate.setTime(currentDate.getTime() + 24 * 60 * 60 * 1000);
    }
    re

turn dateArray;
    }    
}
Run Code Online (Sandbox Code Playgroud)

我确定这是正确的方法,并希望这将是有益的


小智 9

就像Deyd之前指出的那样,这是由Angular 2 +的变化检测和ng2-charts中的错误组合引起的.

根据我自己的观察(如果我错了,请纠正我),Angular会在很短的时间内将几个变化合并到一个集合(changes: SimpleChanges)中ngOnChanges.

不幸的是,ng2-charts只检查数据集是否已使用此集合进行更改并更新它.否则它会完全重建整个图表.但是,由于更改检测的工作方式,可能会更改多个属性.然后,即使标签和可能的其他属性也已更新,只有数据集才会更新.参见ngOnChangesng2-charts:valor- software/ng2-charts/src/charts/charts.ts

如果您不想在应用程序中单独复制ng2-charts并自行解决问题,则此问题的可能解决方法是使用JavaScript的内置函数设置数据集的延迟很短setTimeout(callback: () => void, delay: number).

之前:

@Component({
  selector: 'app-root',
  template: `
  <select (change)="onChange($event.target.value)">
    <option value="" disabled selected>Select your option</option>
    <option value="0">Option 0</option>
    <option value="1">Option 1</option>
  </select>

  <canvas baseChart
          chartType="bar"
          [datasets]="barChartData"
          [labels]="barChartLabels"
          [colors]="barChartColors">
  </canvas>
  `
})
export class AppComponent implements OnInit {
  chartData: string[];
  chartLabels: string[];
  chartColors: string[];

  onChange(id: string) {
    getFromApiById(id)
      .then(result => this._setChart(result.data, result.labels, result.colors));
  }

  private _setChart(data: string[], labels: string[], colors: string[]) {
    this.chartData = data;
    this.chartLabels = labels;
    this.chartColors = colors;
  }
}
Run Code Online (Sandbox Code Playgroud)

后:

@Component({
  selector: 'app-root',
  template: `
  <select (change)="onChange($event.target.value)">
    <option value="" disabled selected>Select your option</option>
    <option value="0">Option 0</option>
    <option value="1">Option 1</option>
  </select>

  <canvas baseChart
          chartType="bar"
          [datasets]="barChartData"
          [labels]="barChartLabels"
          [colors]="barChartColors">
  </canvas>
  `
})
export class AppComponent implements OnInit {
  chartData: string[];
  chartLabels: string[];
  chartColors: string[];

  onChange(id: string) {
    getFromApiById(id)
      .then(result => this._setChart(result.data, result.labels, result.colors));
  }

  private _setChart(data: string[], labels: string[], colors: string[]) {
    this.chartLabels = labels;
    this.chartColors = colors;

    setTimeout(() => {
      this.chartData = data;
    }, 50);
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 5

诀窍在于清除标签和数据数组,下面的代码对我不起作用:( ```

clearCharts() {
    this.barChartLabels= [];
    this.barChartData= [
      {data: [], label: 'label1'},
      {data: [], label: 'label2'}
    ];
  }
Run Code Online (Sandbox Code Playgroud)

However when I changed the way I cleared the data helped me (Using object reference)

clearCharts() {
    this.barChartLabels= [];
    this.emptyChartData(this.barChartData);
  }
   emptyChartData(obj) {
     obj[0].data = [];
     obj[1].data = [];
     obj[0].label = 'label1';
     obj[1].label = 'label2';
  }
Run Code Online (Sandbox Code Playgroud)

````


小智 5

使用BaseChartDirective我做了图表更新,它达到了目的.以下示例:

import { BaseChartDirective } from 'ng2-charts/ng2-charts';
Run Code Online (Sandbox Code Playgroud)

在课堂内添加如下

@ViewChild(BaseChartDirective) chart: BaseChartDirective;
Run Code Online (Sandbox Code Playgroud)

当您要更改值时,请添加如下

setTimeout(() => {
if (this.chart && this.chart.chart && this.chart.chart.config) {
  this.chart.chart.config.data.labels = this.labels_pie;
  this.chart.chart.update();
}
});
Run Code Online (Sandbox Code Playgroud)


小智 5

使用 BaseChartDirective 我进行了图表更新,它达到了目的。示例如下:

import { BaseChartDirective } from 'ng2-charts';
Run Code Online (Sandbox Code Playgroud)

在类中添加如下

@ViewChild(BaseChartDirective) chart: BaseChartDirective;
Run Code Online (Sandbox Code Playgroud)

当您有要更改的值时,请添加如下

 this.chart.ngOnChanges({});
Run Code Online (Sandbox Code Playgroud)