Unusual behaviour of ngFor

我的梦境 提交于 2020-01-01 19:43:08

问题


Today i was trying angular directive ngFor. The problem i am facing is that when i select any checkbox (for e.g. 0) and click "next" , if next question also have the same option (0) as i have selected in previous question then it will be checked automatically, i dont know how?? [This behaviour is not seen if any two or more consecutive questions doesnt have alteast one same option. ]. I hope it make sense. here is my plunker

template:

    {{question}}
    <div *ngFor="let option of options">
      <input type="checkbox">{{option}}<br>
    </div>

  <button (click)="onNext()">next</button>

Component.ts

export class App implements OnInit {
    private questionPaper = {
        questions: [{
                _id: "59d1cbd4f8a709358c045696",
                question: "2 + 3",
                __v: 0,
                answers: [
                    "5"
                ],
                options: [
                    "0",
                    "1",
                    "5",
                    "3",
                    "6"
                ]
            },
            {
                _id: "59d1cbf7f8a709358c045698",
                question: "1 * 3",
                __v: 0,
                answers: [
                    "3"
                ],
                options: [
                    "1",
                    "3",
                    "0",
                    "4"
                ]
            },
            {
                _id: "59d1cc18f8a709358c045699",
                question: "3 - 3",
                __v: 0,
                answers: [
                    "0"
                ],
                options: [
                    "3",
                    "0",
                    "6",
                    "4",
                    "7"
                ]
            },
            {
                _id: "59d1cc3ef8a709358c04569a",
                question: "6 - 4",
                __v: 0,
                answers: [
                    "2"
                ],
                options: [
                    "2",
                    "3",
                    "4",
                    "0",
                    "6"
                ]
            },
            {
                _id: "59d1cc71f8a709358c04569b",
                question: "4 * 8",
                __v: 0,
                answers: [
                    "32"
                ],
                options: [
                    "4",
                    "8",
                    "12",
                    "32",
                    "23"
                ]
            },
            {
                _id: "59d1cc96f8a709358c04569c",
                question: "0 * 1",
                __v: 0,
                answers: [
                    "0"
                ],
                options: [
                    "0",
                    "1",
                    "10",
                    "-1",
                    "4"
                ]
            },
            {
                _id: "59d1cccdf8a709358c04569d",
                question: "6 + 6",
                __v: 0,
                answers: [
                    "12"
                ],
                options: [
                    "6",
                    "12",
                    "21",
                    "0"
                ]
            },
            {
                _id: "59d1fb6a253c5270115f4ced",
                question: "1 + 10",
                __v: 0,
                answers: [
                    "11"
                ],
                options: [
                    "11"
                ]
            }
        ]
    };

    private question;
    private options = [];
    private currentQuesNumber = 1;
    onInit() {}
    constructor() {
        this.question = this.questionPaper.questions[0].question;
        this.options = this.questionPaper.questions[0].options;

    }

    onNext() {

        if (this.currentQuesNumber >= this.questionPaper.questions.length) {
            this.loadQuestion(this.questions.length);

        } else {

            this.currentQuesNumber = this.currentQuesNumber + 1;
            this.loadQuestion(this.currentQuesNumber);

        }
    }



    loadQuestion(quesNumbToLoad) {
        if (quesNumbToLoad > 0 && quesNumbToLoad <= this.questionPaper.questions.length) {
            this.question = this.questionPaper.questions[quesNumbToLoad - 1].question;

            this.options = this.questionPaper.questions[quesNumbToLoad - 1].options;
        }

    }

}

回答1:


That is the indented behavior because angular resuses DOM elements inside it's ngForOf-directive for better performance, based on the object identity of the value. So in your case the value is a string, that means the object identity is its value.

Therefore angular is reusing the DOM element if the value of an option is the same between questions. Because the same DOM element is used the checkbox state is still checked.

If you want angular to not reuse DOM elements inside an ngForOf-directive, you have to provide a function which always returns some sort of a unqiue id (e.g. the current datetime) and apply it to the ngForTrackBy input of the ngForOf-directive (short-syntax trackBy).


For example:

Component

public trackById(index: number, value: any) {
  return Date.now();
}

Component template

*ngFor="let option of options;trackBy:trackById"

or:

<ng-template ngFor let-option [ngForOf]="options"[ngForTrackBy]="trackByFn">
</ng-template>

Now angular doesn't reuse any DOM elements for this ngForOf-directive.

More about the change propagation of the ngForOf-directive can be found in the docs (and some useful other stuff about it).


Note: This also works also the opposite way. For example if you have some immutable data and you don't want new DOM elements to be created on every change. Just provide a function which returns the current index of the item. This will force angular into reusing every existing DOM-element inside your ngForOf-directive regardless of the object identity.



来源:https://stackoverflow.com/questions/46535126/unusual-behaviour-of-ngfor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!