Dynamically updated ng2-charts

2019-06-21 19:23发布

Is it possible to update any chart from ng2-charts dynamically? I know there are other libraries like angular2-highcharts, but I would like to handle it using ng2-charts. Main question is how can I redraw chart, after button click? I can resize window and data will be updated, so it have to be any option to do it manually.

https://plnkr.co/edit/fXQTIjONhzeMDYmAWTe1?p=preview

6条回答
虎瘦雄心在
2楼-- · 2019-06-21 19:54

Recently I had to use ng2-charts and i was having a very big issues with updating my data until I found this solution:

<div class="chart">
        <canvas baseChart [datasets]="datasets_lines" [labels]="labels_line" [colors]="chartColors" [options]="options" [chartType]="lineChartType">
        </canvas>
</div>

and here what I have in my component :

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.labels_line = this.getDates();

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

                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);
        }
        return dateArray;
    }    
}

I'm sure this is the right way to do it.

查看更多
虎瘦雄心在
3楼-- · 2019-06-21 19:55

Update any chart from ng2-charts dynamically is possible. Example: http://plnkr.co/edit/m3fBiHpKuDgYG6GVdJQD?p=preview

That Angular update chart, variable or reference must change. When you just change value of array element, variables and references not changed. See also Github.

查看更多
一纸荒年 Trace。
4楼-- · 2019-06-21 19:56

A good way is to get a grip on the chart itself in order to redraw it using the API :

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

  private updateChart(){
   this.chart.ngOnChanges({});
  }

}
查看更多
孤傲高冷的网名
5楼-- · 2019-06-21 20:02

I figure it out, maybe its not the best existing option, but it works. We can't update existing chart, but we can create new one, using our existing chart and add new points. We can even get better effect, turning animation of chart off.

Function that solved problem:

updateChart(){
   let _dataSets:Array<any> = new Array(this.datasets.length);
   for (let i = 0; i < this.datasets.length; i++) {
      _dataSets[i] = {data: new Array(this.datasets[i].data.length), label: this.datasets[i].label};
      for (let j = 0; j < this.datasets[i].data.length; j++) {
        _dataSets[i].data[j] = this.datasets[i].data[j];
      }
   }
   this.datasets = _dataSets;
}

Live demo: https://plnkr.co/edit/fXQTIjONhzeMDYmAWTe1?p=preview

@UPDATE: as @Raydelto Hernandez mentioned in comment below, better solution is:

updateChart(){
    this.datasets = this.dataset.slice()
}
查看更多
别忘想泡老子
6楼-- · 2019-06-21 20:05

I have found this article after a searching a while. Then I tried every solution that is mentioned in this article but none was working properly. Finally I settled using a dynamic component.

I provided the dynamic data to component that is dynamically added to the parent component. I wrote about the whole process just so you don't go through the challenges.

查看更多
该账号已被封号
7楼-- · 2019-06-21 20:10

**This worked for me - with pie-chart:*

Component.html:

 <canvas baseChart [colors]="chartColors" [data]="pieChartData" [labels]="pieChartLabels" [chartType]="pieChartType"></canvas>

Component.ts:

In the header section:

import { Component, OnInit, ViewChild, ElementRef } from '@angular/core';
import { Chart } from 'chart.js';
import { BaseChartDirective } from 'ng2-charts/ng2-charts';

In the declaration section of export class:

@ViewChild(BaseChartDirective) chart: BaseChartDirective;
// for custom colors
public chartColors: Array<any> = [{
backgroundColor: ['rgb(87, 111, 158)', 'yellow', 'pink', 'rgb(102, 151, 185)'],
borderColor: ['white', 'white', 'white', 'white']
}];

After the block that updates your pie chart data (using services/sockets or any other means):

this.chart.chart.update();
查看更多
登录 后发表回答