Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular2 method binding error: "value has changed after it was checked"

I am trying to make a circle board in Angular2. For the example I want to make 10 circles but in reality this number can change. I want to calculate the radius of each circle, so it would be dynamic and not static. See the picture for exampleenter image description here

This is my code

@Component({
    selector:"circle"
    template: `
  <svg>
    <circle *ngFor='#item of forLength #i=index #l=last #e=even'
            cx="50%" cy="50%" [style.r]="calculateRadius()" stroke="black" stroke-width="5" fill="white"></circle>
  <svg/>  
    `
})

export class CircleComponent{
    public maxRadius:number=25;
    public totalRounds:number=10;
    public x:number=30;

    public calculateRadius():number{
        var distanceBetweenCircles=this.maxRadius/(this.totalRounds-1);
        this.x-= distanceBetweenCircles;
        return this.x;
    }
}

But I get the following error:

calculateRadius() in CircleComponent@7:30' has changed after it was checked. 
    Previous value: '-7.500000000000007'. 
    Current value: '-36.66666666666668' in [calculateRadius() in CircleComponent@7:30]

Is there maybe a better way of writing this for loop with *ngFor instead of writing this in a separate method?

like image 586
Claudiu Matei Avatar asked Dec 06 '22 18:12

Claudiu Matei


1 Answers

In development mode (the default), change detection is run twice to ensure that model changes have stabilized. This means that the ngFor loop is evaluated twice. Hence property x will continue to be decremented the second time change detection runs. Other activity in your app will also cause change detection to run, and x will continue to be decremented. Therefore, you must write all view functions, like calculateRadius(), assuming they will be executed many times. E.g.:

public calculateRadius(i):number{
    return this.x - i*this.distanceBetweenCircles;
}

The Template Syntax dev guide mentions this when it describes idempotent expressions.

This will also solve the value has changed after it was checked problem.

You also need to bind SVG attribute r using this syntax: [attr.r]="...", not [style.r]="...".

Plunker

like image 180
Mark Rajcok Avatar answered Dec 09 '22 13:12

Mark Rajcok