0

I'm trying to update the values of my chart after aplying or clearing filters with the following code

 <div class="col-xs-8 card-container" style="padding: 0 0 0 0">
<mat-card  height="100%" style="padding: 16px 0px 16px 16px !important; height:100%">
    <mat-card-title style="text-align:center;">Gráfica</mat-card-title>
    <mat-card-content>
        <div style="display: block; width: 100%" id="canvasContainer" *ngIf="!emptyData()">
            <canvas  id="myChart"></canvas>   
        </div>
        <div style="display: block; width: 100%" *ngIf="emptyData()">
            <h3>Pendiente de evaluar.</h3>
        </div>
    </mat-card-content> 
</mat-card>

this is the html where I render the chart on the canvas with id myChart

this is the code where I generate my first chart, it only executes once and it works

  setup(): void{
const maxValue = this.getMaxValue();
var ctddx = document.getElementById('myChart');
var canvas = <HTMLCanvasElement> document.getElementById('myChart');
if(canvas !== null) {
this.ctx = canvas.getContext("2d");
      this.chart= new Chart(this.ctx, {
      type: 'bar',
      data: {
        labels: this.labels,
        datasets: [{
            data: this.values,
            borderWidth: 3,
            fillColor: this.colors,
            backgroundColor: this.colors,
            borderColor: this.colors
        }]
    },
      options: {
        responsive: true,
        legend: {
            display: false
        },
        hover: {
            mode: 'label'
        },
        scales: {
            yAxes: [{
                ticks: {
                    beginAtZero: true,
                    callback: function (value) { if (Number.isInteger(value)) { return value; } },
                    suggestedMax: maxValue,
                }
            }],
            xAxes: [{
              fontSize: 35,
              barThickness : 65
          }],
        },

        plugins: {
            datalabels: {
                // align: 'start',
                // anchor: 'start',
                clamp: true,
            }
        }
      }
    });
    this.initialized = true;
  }
 }

till this point the code works and render the first chart correctly. Now when I try to apply filters or clear filters it doesn't render anything this is the following code

 modifyChart(labels,values){
  let oldchart = this.chart;
  this.removeData();
  this.addData(labels,values);
  console.log(oldchart===this.chart);
  }

   removeData() {
    this.chart.data.labels.pop();
    this.chart.data.datasets.forEach((dataset) => {
    dataset.data.pop();
   });
   this.chart.update();
}
 addData(label, data) {
  this.chart.data.labels.push(label);
  this.chart.data.datasets.forEach((dataset) => {
  dataset.data.push(data);
  });
 this.chart.update();
}

It doesn't work, it render nothing and I even tried to compare previously chart with new chart introducing the same values it had, and it returns true, so even being the same Chart, it isn't rendering

I think the problem has to be because update deletes de canvas and create it again, but after a while I can't find a workaround

JoseCarlosPB
  • 933
  • 2
  • 14
  • 29

1 Answers1

1

Ok, so I managed to fix this, I hope this answer can help someone who faces the same problem with re rendering Charts on the same canvas if update doesn't work.

first of all I had this lifecycle method

  ngAfterContentChecked(): void {
if (!this.initialized && !this.emptyData()) {
    this.setup();
  }
}

So I can render the first chart it can't be done on OnInit because you need the canvas to be ready, so with this I'm always waiting for canvas to be ready like my method setup I posted on the question

 setup(): void{
  const maxValue = this.getMaxValue();
  var canvas = <HTMLCanvasElement> document.getElementById('myChart');
  if(canvas !== null) {
        ...
  this.initialized = true;
     }
  }

the problem with Update I think that it also destroys the canvas and create a new one with the same Id, so I think it tries to render the chart before the canvas is ready, so I made a workaround like this

after applying all filters needed and retrieving the new data

modifyChart() {
this.chart.destroy();
this.initialized = false;
}

with this code, my ngAfterContentChecked is going to call for setup till canvas is ready and change initialized to true again

I know this is probably not the best workaround, but at least it fixed my problem

JoseCarlosPB
  • 933
  • 2
  • 14
  • 29