0

ngModel with ngFor and trackBy: trackByIndex isnt working as expected. This is my html template:

<form (ngSubmit)="createTest()" #testForm="ngForm">
            <div class="card" *ngFor="let question of questionsArr; let i=index;">
                <div class="card-header">
                    <input type="text" placeholder="Question {{i+1}}" name="question{{i}}"  class="form-control" [(ngModel)]="questionsArr[i].text">
                </div>
                <div class="card-block" *ngFor="let option of fillArray(oC); let u=index">
                    <input type="text" class="form-control" placeholder="Option {{u+1}}" name="option" id="option">
                </div>
            </div>
    </form>
The below works well. But in the above, [(ngModel)]="questionsArr[i].text" seems to bind to the same thing regardless.

<label *ngFor="let item of items; let i=index; trackBy:trackByIndex">
    {{items[i]}}
    <input type="number" [(ngModel)]="items[i]">
</label>.

I did some testing and used an array of objects with the below array of objects and it works as its supposed to:

 testarr = [
  {
    a: "a",
    b: "b"
  },
  {
    a: "aa",
    b:"bb"
  }
  ];

to do some testing, it worked. changing ngModel to just questionsArr[i] also yielded a separate object for every iteration. The problem seems to be that [(ngModel)]="questionsArr[i].text" doesn't work as its supposed to.

questionsArr is just an array of this: 'new QuestionModel("Question Text", this.s.name, "",null);'

This is the relevant part of my component:

optionsArr: OptionModel[];
    questionsArr: QuestionModel[];

    blankQM: QuestionModel;
    blankOM: OptionModel;
    formTest: TestModel;

    items: number[] = [1,2,3,4,5];

  constructor(
    private api: ApiService
  ) { }

  ngOnInit() {
    this.blankQM = new QuestionModel("Question Text", this.s.name, "",null);
    this.blankOM = new OptionModel("Option Text");
    this.formTest = new TestModel("", null);
    this._getQuestionArrays();
    this._getOptionArrays();
  }

  _getQuestionArrays(){
    // this.fillArray(this.qC);
    this.questionsArr = Array(this.qC).fill(this.blankQM);
  }

  _getOptionArrays(){
    // this.fillArray(this.oC);
    this.optionsArr = Array(this.oC * this.qC).fill(this.blankOM);
    }

  fillArray(qty){
    return Array(qty).fill(0).map((e,i)=> i+ 1);
  }

  goBack(){
    this.back.emit();
  }

  createTest(){
    console.log(this.questionsArr);
    // console.log(this.optionsArr);

    console.log(this.testarr);
  }


  trackByIndex(index: number, value: QuestionModel){
    return index;
  }

  testarr = [
  {
    a: "a",
    b: "b"
  },
  {
    a: "aa",
    b:"bb"
  }
  ];
} 

From what I've gathered i'm to use trackBy, and it does what its supposed, i don't just know why I cant get ngModel it to bind to the correct questionsArr[i].text accessing the text property of the correct index of questionsArr as accessing questionsArrenter code here works Ok enough.

IdiakosE Sunday
  • 112
  • 1
  • 8
  • What's the error you get when you try to bind to [(ngModel)]? – BogdanC Oct 01 '17 at 01:40
  • I don't get an error, just that when I bind ngModel to questionsArr[I].text it only binds to the last item in the array. it doesn't track it as expected. it binds the same item to all the inputs. – IdiakosE Sunday Oct 01 '17 at 10:50

1 Answers1

0

Turns out the

Array.fill

i did was the problem. Changed my code to use a for loop to populate the array instead.

IdiakosE Sunday
  • 112
  • 1
  • 8