Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

angularjs - 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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...