首页 > 解决方案 > Angular 在同一页面渲染中动态创建图表线始终是最后一个数据值

问题描述

我已经创建了一个图表组件,我想在其他组件中动态地将它渲染到 ng-for 中。问题是图表总是呈现所有图表的最后一个值。如果我检查页面,画布具有正确的值。我留下了一个粘贴箱。谢谢你。

这是我的代码:

//line-chart.config.ts

import { CurrencyPipe } from "@angular/common";
import { ChartConfiguration } from "chart.js"
 
export function updateLineChartConfig(labels: string[], data: number[], data2?: any): ChartConfiguration {
  const config: ChartConfiguration = lineChartConfig;
  console.log('config1:', config)
  config.data.labels = labels;
  config.data.datasets[0].data = data;
  if (data2) {
    config.data.datasets[1].label = data2.Year.toString();
    config.data.datasets[1].data = [{ x: data2.Year, y: data2.Im }];
  }
  return config;
}
 
export const lineChartConfig: ChartConfiguration = {
  type: 'line',
  data: {
    labels: [],
    datasets: [{
      label: '',
      data: [],
      backgroundColor: [
        'rgba(255, 99, 132, 0.2)',
        'rgba(54, 162, 235, 0.2)',
        'rgba(255, 206, 86, 0.2)',
        'rgba(75, 192, 192, 0.2)',
        'rgba(153, 102, 255, 0.2)',
        'rgba(255, 159, 64, 0.2)'
      ],
      borderColor: [
        'rgba(255, 99, 132, 1)',
        'rgba(54, 162, 235, 1)',
        'rgba(255, 206, 86, 1)',
        'rgba(75, 192, 192, 1)',
        'rgba(153, 102, 255, 1)',
        'rgba(255, 159, 64, 1)'
      ],
      borderWidth: 1
    },
       {
        label: '',
         data: [],
         borderColor: [
           'rgba(75, 192, 192,1)',
         ],
         borderWidth: 2
       }
    ]
  },
  options: {
    legend: {
      display: false,
    },
    scales: {
      yAxes: [{
        ticks: {
          beginAtZero: true,
          callback: function (value, index, values) {
            const v = +value / 1000
            return new CurrencyPipe('it-IT').transform(v, 'EUR');
          }
        }
      }]
    },
    tooltips: {
      callbacks: {
        label: function (tooltipItem, chart) {
          var datasetLabel = chart.datasets[tooltipItem.datasetIndex].label || '';
 
          return new CurrencyPipe('it-IT').transform(tooltipItem.value, 'EUR');
        },
        title: function (tooltipItem, chart) {
          return chart.datasets[tooltipItem[0].datasetIndex].label || tooltipItem[0].label || '';
        }
      }
    }
  }
}

//line.chart.component.ts

import { AfterViewInit, Component, ElementRef, Input, SimpleChanges, ViewChild } from '@angular/core';
import * as Chart from 'chart.js';
import { updateLineChartConfig } from './line-chart.config';
 
@Component({
  selector: 'app-line-chart',
  templateUrl: './line-chart.component.html',
  styles: [``]
})
export class LineChartComponent implements AfterViewInit {
  @ViewChild("lineChart", { static: true }) lineChart: ElementRef<HTMLCanvasElement>;
 
  @Input() data: number[]
  @Input() data2: number[]
  @Input() labels: string[]
  @Input() titleChart: string;
 
  myChart: Chart;
  constructor() { }
 
  ngAfterViewInit(): void {
 
  }
 
  ngOnChanges(changes: SimpleChanges) {
    console.log(changes)
    const { data, data2, labels } = changes;
 
    const config = updateLineChartConfig(labels.currentValue, data.currentValue, null)
 
    if (!data) return;
    if (data.firstChange) {
      const ctx = this.lineChart.nativeElement.getContext('2d');
      this.myChart = new Chart(ctx, config);
    }
    else {
      console.log('NO')
      this.myChart.config = config;
      this.myChart.update();
    }
  }
 
}

//.html

<div class="modal-header">
  <h4 class="modal-title">Fatturato</h4>
  <button type="button" class="close" aria-label="Close" (click)="activeModal.dismiss('ko')">
    <span aria-hidden="true">&times;</span>
  </button>
</div>
<div class="modal-body">
  <div class="row d-flex justify-content-center" *ngIf="purchasedValue$|async; else loading">
    <app-line-chart class="col-6" [data]="purchasedValue$|async" [data2]="purchasedValueAtData$|async"
      [labels]="purchasedYears$|async" titleChart="Totale">
    </app-line-chart>
  </div>
  <span class="row" *ngIf="listLine$|async; else loading">
    <div class="col-6" *ngFor="let item of listLine$|async">
      {{item|json}}
      <app-line-chart [data]="item.TyLine|purchasedLineValue|async" [labels]="item.TyLine|purchasedLineYear|async">
      </app-line-chart>
    </div>
  </span>
 
</div>
<div class="modal-footer">
  <button type="button" class="btn btn-outline-primary" (click)="activeModal.close()">Ok</button>
</div>
 
<ng-template #loading>
  <strong>Loading...</strong>
  <div class="spinner-grow ml-auto" role="status" aria-hidden="true"></div>
</ng-template> 

//.ts

import { Component, OnInit } from '@angular/core';
import { NgbActiveModal } from '@ng-bootstrap/ng-bootstrap';
import { select, Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { AppState } from 'src/app/app.module';
import { getPurchasedValue, getPurchasedValueAtDate, getPurchasedYear } from '../../store/supplier.selectors';
import { getListLine } from './../../store/supplier.selectors';
 
@Component({
  selector: 'app-purchased-modal',
  templateUrl: './purchased-modal.component.html',
  styles: [`
    .light-blue-backdrop {
      background-color: #5cb3fd;
    }
  `]
})
export class PurchasedModalComponent implements OnInit {
 
  purchasedYears$: Observable<number[]> = this.store.pipe(select(getPurchasedYear));
  purchasedBeforeYears$: Observable<number[]> = this.store.pipe(select(getPurchasedYear));
  purchasedValue$: Observable<number[]> = this.store.pipe(select(getPurchasedValue));
  purchasedValueAtData$: Observable<number> = this.store.pipe(select(getPurchasedValueAtDate));
  listLine$: Observable<any[]> = this.store.pipe(select(getListLine));
 
  constructor(public activeModal: NgbActiveModal, private store: Store<AppState>) { }
 
  ngOnInit(): void {
  }
 
}

标签: javascriptangularcanvaschart.jsngfor

解决方案


推荐阅读