'Dynamically update doughnut chart with NG2Charts

I am working on a project where I am making a calculator of macronutrients. I have a form to enter the values and it displays a doughnut chart, with its initial values at 0. But when I click the submit button, the chart does not update.

Here is my code:

home.component.html

<form (submit)="addMeal(totalGrams, proteinGrams, fatGrams, carbGrams)">
              <div class="form-group">
                <input
                  class="form-control"
                  type="number"
                  placeholder="Total"
                  #totalGrams
                />
              </div>
              <div class="form-group">
                <input
                  class="form-control"
                  type="number"
                  placeholder="Protein"
                  #proteinGrams
                />
              </div>
              <div class="form-group">
                <input
                  class="form-control"
                  type="number"
                  placeholder="Fat"
                  #fatGrams
                />
              </div>
              <div class="form-group">
                <input
                  class="form-control"
                  type="number"
                  placeholder="Carbs"
                  #carbGrams
                />
              </div>

              <button type="submit" class="btn btn-primary btn-block">
                Enviar
              </button>
            </form>

I have provided only the form code because there is a big layout and many bootstrap components that do not really affect the core problem.

home.component.ts

import { Component, ViewChild } from '@angular/core';
import { ChartData, ChartType } from 'chart.js';

@Component({
  selector: 'app-home',
  templateUrl: './home.component.html',
  styleUrls: ['./home.component.css']
})
export class HomeComponent {

  gProtein: number = 0;
  gCarbs: number = 0;
  gFat: number = 0;

  public doughnutChartLabels: string[] = [ 'Proteína', 'Carbohidratos', 'Grasa' ];
  public doughnutChartData: ChartData<'doughnut'> = {
    labels: this.doughnutChartLabels,
    datasets: [
      { data: [ this.gProtein, this.gCarbs, this.gFat ] },
    ]
  };
  public doughnutChartType: ChartType = 'doughnut';

  addMeal(totalGrams: HTMLInputElement, proteinGrams: HTMLInputElement, fatGrams: HTMLInputElement, carbGrams: HTMLInputElement) {
    this.doughnutChartData.datasets[0].data[0] = parseInt(proteinGrams.value);
    this.doughnutChartData.datasets[0].data[1] = parseInt(carbGrams.value);
    this.doughnutChartData.datasets[0].data[2] = parseInt(fatGrams.value);
    totalGrams.value = ''
    proteinGrams.value = ''
    fatGrams.value = ''
    carbGrams.value = ''
    totalGrams.focus()    
    return false;
  }

}

I don't know when the last time this library was updated, but this is the way the documentation says you have to update your chart (other types of chart since the doughnut documentation is not really well written, imo).



Solution 1:[1]

It happened the same to me. The documentation is actually well written, but it does not cover every single scenario for every single chart, so you have to look for that thing you are asking in other chart. I solved it by looking at the bar chart, and what you have to do is this.

Inside your .ts component, import this:

import { BaseChartDirective } from 'ng2-charts';

Then, this:

@ViewChild(BaseChartDirective) chart?: BaseChartDirective;

And the last thing you have to do is this (I formatted your addMeal() method in order to read it better):

addMeal(
    totalGrams: HTMLInputElement,
    totalCals: HTMLInputElement,
    proteinGrams: HTMLInputElement,
    fatGrams: HTMLInputElement,
    carbGrams: HTMLInputElement
  ) {
    this.doughnutChartData.datasets[0].data[0] =
      parseInt(totalCals.value) * (parseInt(totalGrams.value) / 100);
    this.doughnutChartData.datasets[0].data[1] =
      parseInt(proteinGrams.value) * (parseInt(totalGrams.value) / 100);
    this.doughnutChartData.datasets[0].data[2] =
      parseInt(carbGrams.value) * (parseInt(totalGrams.value) / 100);
    this.doughnutChartData.datasets[0].data[3] =
      parseInt(fatGrams.value) * (parseInt(totalGrams.value) / 100);
    this.chart?.chart?.update();
    totalGrams.value = '';
    totalCals.value = '';
    proteinGrams.value = '';
    fatGrams.value = '';
    carbGrams.value = '';
    return false;
  }

As you can see, I have only added one line, right before you set to empty your form fields, the update() method.

I would like to give you an advice, which is to read the full documentation, or at least all the documentation for the thing you are working with before you ask something, because this thing was very well explained here.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 AhmedSHA256