Angular 9 ChartJS не обновляет представление после обновления данных

#angular #chart.js #angular9

#angular #chart.js #angular9

Вопрос:

Вначале все работает хорошо. Эта функция вызывается, когда выбран временной диапазон (LAST_SEVEN_DAYS, LAST_THIRTY_DAYS и т. Д.). Функция вызывает серверную часть и получает результат, а затем обновляет представление

   loadInstallEvolution(periodRange, label) {

    this.selectedRatingRangeLabel = label;
    const apkIdToUse = sessionStorage.getItem(url.apkIdInUse);
    this.installChartData.datasets[0].data = [0, 0, 0, 0, 0, 0, 0];
    this.installChartData.labels = [];
    this.isLoading = true;
    if (!apkIdToUse) {
      this.isNoDataFound = true;
    } else {
      // tslint:disable-next-line:no-unused-expression
      const param = { historyRange :  periodRange, apkId : Number(apkIdToUse)};
      this.searchApkControllerService.findInstallHistoryUsingGET(param).subscribe(
        (reviewList) => {

          let index = 0;
          let max = 0;
          let firstValue = 0;

          for (let [key, value] of Object.entries(reviewList)) {
            // change the date format
            if (periodRange === 'LAST_SEVEN_DAYS' || periodRange === 'LAST_THIRTY_DAYS' ) {
              key = this.datepipe.transform(key, 'MM/dd');
            }

            this.installChartData.datasets[0].data[index] = value;
            this.installChartData.labels[index] = key;
            // get first value;
            if (index === 0) {
              firstValue = value;
            }
            // calculate the max of y axis
            if (max < value) {
              max = value;
            }
            index  ;
          }

          // update the axis
          this.chartDataConfig.areaChartOptions.scales.yAxes[0].ticks.max = max   20;
          this.chartDataConfig.areaChartOptions.scales.yAxes[0].ticks.beginAtZero = false;
          this.isLoading = false;
        },
        (error) => {
          this.notifications.create(
            'Error',
            error.error.message,
            NotificationType.Error,
            { theClass: 'outline primary', timeOut: 6000, showProgressBar: false }
          );
          this.isLoading = false;
        }
      );
    }
  }
 

Поскольку у меня несколько диаграмм, вместо того, чтобы делать несколько вызовов для каждой диаграммы, я решил сделать один вызов, затем все диаграммы обновляются при появлении новых данных.

Затем я добавил

   ngOnInit() {
    this.sharevariableService.getApkHistoryDto().subscribe((apkHistory) => {
      if(apkHistory != null) {
        this.loadInstallEvolution(apkHistory);
      }
    });

  }
 

тогда моя функция становится:

  loadInstallEvolution(apkHistoryDto: ApkHistoryDto) {

        console.log("loadInstallEvolution apps install");
        const apkIdToUse = sessionStorage.getItem(url.apkIdInUse);
        this.installChartData.datasets[0].data = [0, 0, 0, 0, 0, 0, 0];
        this.installChartData.labels = [];
        this.isLoading = true;
    
        if (!apkIdToUse) {
          this.isNoDataFound = true;
        } else {
    
    
          let index = 0;
          let max = 0;
          let firstValue = 0;
    
          for (let [key, value] of Object.entries(apkHistoryDto.installHistory)) {
            // change the date format
            if (apkHistoryDto.historyRange === 'LAST_SEVEN_DAYS' || apkHistoryDto.historyRange === 'LAST_THIRTY_DAYS' ) {
              key = this.datepipe.transform(key, 'MM/dd');
            }
    
            this.installChartData.datasets[0].data[index] = value;
            this.installChartData.labels[index] = key;
    
            // get first value;
            if (index === 0) {
              firstValue = value;
            }
            // calculate the max of y axis
            if (max < value) {
              max = value;
            }
            index  ;
          }
          // update the axis
          //this.installChartData.datasets[0].data = [...this.installChartData.datasets[0].data];
          console.log(this.installChartData);
          this.chartDataConfig.areaChartOptions.scales.yAxes[0].ticks.max = max   20;
          this.chartDataConfig.areaChartOptions.scales.yAxes[0].ticks.beginAtZero = false;
          this.isLoading = false;
        }
      }
 

С помощью этой новой функции моя диаграмма не обновляется. Переменные установлены правильно, но нет способа обновить представление.

в моем app-install-eveolution-chart.component.html у меня есть:

   <app-area-chart [shadow]="true" class="chart" [options]="chartDataConfig.areaChartOptions"
                  [data]="installChartData"></app-area-chart>
 

и app-area-chart это еще один компонент
area-chart.component.html

 <div [class]="class"><canvas #chart></canvas></div>
 

и area-chart.component.ts

 export class AreaChartComponent implements AfterViewInit, OnDestroy {

  @Input() shadow = false;
  @Input() options;
  @Input() data;
  @Input() class = 'chart-container';
  @ViewChild('chart', { static: true }) chartRef: ElementRef;

  chart: Chart;

  public constructor() {
    Chart.defaults.global.defaultFontColor = 'white';
  }

  ngAfterViewInit() {
    if (this.shadow) {
      Chart.defaults.lineWithShadow = Chart.defaults.line;
      Chart.controllers.lineWithShadow = Chart.controllers.line.extend({
        draw(ease) {
          Chart.controllers.line.prototype.draw.call(this, ease);
          const chartCtx = this.chart.ctx;
          chartCtx.save();
          chartCtx.shadowColor = 'rgba(0,0,0,0.15)';
          chartCtx.shadowBlur = 10;
          chartCtx.shadowOffsetX = 0;
          chartCtx.shadowOffsetY = 10;
          chartCtx.responsive = true;
          chartCtx.stroke();
          Chart.controllers.line.prototype.draw.apply(this, arguments);
          chartCtx.restore();
        }
      });
    }
    console.log("coding is awesome for brain");
    const chartRefEl = this.chartRef.nativeElement;
    const ctx = chartRefEl.getContext('2d');
    this.chart = new Chart(ctx, {
      type: this.shadow ? 'lineWithShadow' : 'line',
      data: this.data,
      options: this.options
    });
  }

  ngOnDestroy() {
    if (this.chart) {
      this.chart.destroy();
    }
  }
}
 

Я безуспешно пробовал многие решения.
Во время тестирования с первым старым решением после каждых новых данных я могу войти внутрь ngAfterViewInit и получить свой console.log. С новым решением у меня это только в первый раз, а не когда у меня есть обновление, ничего не происходит.

Пожалуйста, у вас есть какие-либо идеи? Любая помощь, пожалуйста? Спасибо

РЕДАКТИРОВАТЬ: я попробовал решение, используя ngOnInit в компоненте для автоматического обнаружения изменений, но эта функция по-прежнему не вызывается.

Комментарии:

1. наконец, найдите решение. ngOnInit() { this.sharevariableService.getApkHistoryDto().subscribe((apkHistory) => { if(apkHistory != null) { this.isLoading = true; setTimeout (() => { this.loadInstallEvolution(apkHistory); }, 10); } }); } и когдазагрузка верна, я показываю счетчик вместо разрыва.

Ответ №1:

наконец, найдите решение.

   ngOnInit() { 
this.sharevariableService.getApkHistoryDto().subscribe((apkHistory) => { 

 if(apkHistory != null) { 
   this.isLoading = true; setTimeout (() => { 
     this.loadInstallEvolution(apkHistory); 
 }, 10); } 

}); } 
 

и когда загрузка верна, я показываю счетчик вместо разрыва.