0

I have a stackblitz here - https://stackblitz.com/edit/svg-donuts-fhnnmo?file=src%2Fapp%2Fdonuts.component.ts

I have three donut charts created with svg stroke-dasharray

The position of each segment should follow on from the previous chart segment

So the first charts segment is 60% then the second charts segment should start at 60%.

I can set the segment position using:

Circumference − All preceding segments’ total length + First segment’s offset = Current segment offset

In the ngFor loop I'm calling a updatePercent function to get the length of the previous segments and starting position.

This works for the first and last segements but not the middle one.

In the console I'm getting the error ExpressionChangedAfterItHasBeenCheckedError and the console log seems to continue more than I was expecting.

What does ExpressionChangedAfterItHasBeenCheckedError mean

import { Component, Input } from '@angular/core';

@Component({
  selector: 'donuts',
  templateUrl: './donuts.template.html'
})


export class DonutsComponent  {
  @Input() donutData: any;

  public startOffset = 25;
  public strokeDashOffset;
  public firstOffset;
  public previousValues = [];

  updatePercent(i:number, donut:any){
    if(donut){
      if(i === 0){
        this.firstOffset = donut.percent
        this.previousValues.push(this.startOffset)
        this.previousValues.push(this.firstOffset)
        this.strokeDashOffset = this.startOffset
      }else{
        this.previousValues.push(donut.percent);
        console.log(this.previousValues.reduce((a, b) => a + b, 0))
        this.strokeDashOffset = 100-this.previousValues.reduce((a, b) => a + b, 0);
      }
    }
  }
}
Amit Chigadani
  • 28,482
  • 13
  • 80
  • 98
ttmt
  • 5,822
  • 27
  • 106
  • 158
  • 1
    `"What does ExpressionChangedAfterItHasBeenCheckedError mean"`: https://blog.angularindepth.com/everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror-error-e3fd9ce7dbb4 – AT82 Oct 10 '18 at 06:09
  • https://stackoverflow.com/questions/43375532/expressionchangedafterithasbeencheckederror-explained/62564534#62564534 – Safal Pillai Jun 25 '20 at 05:52

2 Answers2

0

in this file donuts.template.html

<div>
  <ul>
    <li *ngFor="let donut of donutData; let i = index;">
      {{updatePercent(i, donut)}}  
      <svg width="100%" height="100%" viewBox="0 0 42 42" class="donut">

{{updatePercent(i, donut)}} line in loop is causing this problem. Because you are changing the model before the angular completes its one cycle of change detection.

Vivek Kumar
  • 4,822
  • 8
  • 51
  • 85
  • Here is right. You need to perform this operation 'updatePercent' before rendering to the DOM. – Suresh Kumar Ariya Oct 10 '18 at 07:18
  • Try to understand, you are using `strokeDashOffset` in the `*ngFor` loop. and you are updating its value before the loop is getting completed, so internally angular change detection is saying that "Let me complete the tasking what is doing first before assigning me new task" – Vivek Kumar Oct 10 '18 at 09:00
0

It's an error call to function in .html

You can change the code like

//In your component, use @Input() set, to give value to the donuts

  _donutData:any  //<--create a new variable
  @Input() 
  set donutData(value)
  {
    this._donutData=value;
    //with each value, you calculate the percent
    this._donutData.forEach((x,i)=>{
       this.updatePercent(i, x)

    })
  }

//You donnut.html

<div>
  <ul>
    <!--we iterate over _donutData (the new variable added)-->
    <li *ngFor="let donut of _donutData; let i = index;">
      <!--see that you remove the line {{updatePercent(i, donut)}}  -->
      <svg width="100%" height="100%" viewBox="0 0 42 42" class="donut">
        <circle class="donut-hole" 
         ...
Eliseo
  • 50,109
  • 4
  • 29
  • 67
  • Agree this one, As per my above question comments. – Suresh Kumar Ariya Oct 10 '18 at 07:20
  • Eliseo, I tried your code but I'm not sure it working correctly, the chart segments are not in the correct position - https://stackblitz.com/edit/svg-donuts-2wviqo?file=src%2Fapp%2Fdonuts.component.ts – ttmt Oct 10 '18 at 07:57
  • not use this.strokeDashOffset, use donut.strokeDashOffset (in code and in .html), – Eliseo Oct 10 '18 at 08:08
  • This first segment is now working but the other charts segments are not. The console of the previousValues array shows all values in both outputs. I think the first log should show one value and the second show two values - https://stackblitz.com/edit/svg-donuts-2wviqo?file=src%2Fapp%2Fdonuts.component.ts – ttmt Oct 10 '18 at 08:47