0

I have a list of object like this:

listSubject = [
{name: 'Math', lessonPerWeeks: 1},
{name: 'Lit', lessonPerWeeks: 2},
{name: 'Bio', lessonPerWeeks: 3},
{name: 'Phy', lessonPerWeeks: 7},
{name: 'Remains', lessonPerWeeks: 36},
];

I put them in a loop of input for changing values like this:

<div *ngFor="let subject of listSubject">
<input *ngIf="subject.name != 'Remains'" type="number" [(ngModel)]="subject.lessonsPerWeeks" [formControl]="changeValue">
<div *ngIf="subject.name === 'Remain'">
   {{subject.lessonPerWeeks}}
</div>
</div>

The FormControl: changeValue is used to detect the changes from input to recalculate the percent of each subject over totals:

this.changeValue
        .valueChanges
        .debounceTime(200)
        .subscribe(()=>{
          for(let i=0; i < this.listSubject.length;i++){
            let subject = this.listSubject[i];
            let lastSubject = this.listSubject[this.listSubject.length-1];
            subject.percentSem1 = subject.lessonPerWeeks/ this.totalLessonPerWeeks * 100;


            if(i === this.listSubject.length - 1){
              return;
            }
            else if(i === 0){
              lastSubject.lessonPerWeeks = 36; 

            }
            lastSubject.lessonPerWeeks -= subject.lessonPerWeeks;
          }

        });

Everything works fine except the initial display value in the Inputs. All inputs display the value of the last item on the list. In this case, the value of all inputs is 7 instead of different value. If I remove the [formControl] , all data display exactly Here is the screenshot: Multi Input display enter image description here

I think my problem is use a FormControl for all the input. Please help me to solve this problem. Thank you

TheRemjx
  • 105
  • 1
  • 6

2 Answers2

0

use name attribute as unique for each input. Otherwise input field which are in loop always display value of last item data.

<div *ngFor="let subject of listSubject; let i = index">
<input *ngIf="subject.name != 'Remains'" 
 type="number" name="field_{{i}}" 
 [(ngModel)]="subject.lessonsPerWeeks" [formControl]="changeValue">
<div *ngIf="subject.name === 'Remain'">
   {{subject.lessonPerWeeks}}
</div>
</div>

References are here :

angular2-ngmodel-inside-ngfor-data-not-binding-on-input

angular2-binding-of-name-attribute-in-input-elements-with-ngfor

dynamic-angular2-form-with-ngmodel-of-ngfor-elements

Community
  • 1
  • 1
Partha Sarathi Ghosh
  • 10,936
  • 20
  • 59
  • 84
  • Thank you, Ghosh. I have added name attribute like your answer. But It's still there. But if I move out the [formControl] all data display ok. – TheRemjx Mar 20 '17 at 06:59
  • Actually, I don't like to create different FormControl for each object in the list. But it's work perfect now. Thank you, Ghosh – TheRemjx Mar 20 '17 at 07:20
0

After read the @Partha Sarathi Ghosh answer and comment. I finally found the solution. I added a same FormControl for each object in the list then bind them in HTML. Typescript code:

this.listSubject.forEach((subject)=>{
      subject.changeValue = new FormControl();
      subject.changeValue
          .valueChanges
    .debounceTime(200)
    .subscribe(()=>{
      for(let i=0; i < this.listSubject.length;i++){
        let subject = this.listSubject[i];
        let lastSubject = this.listSubject[this.listSubject.length-1];
        subject.percentSem1 = subject.lessonPerWeeks/ this.totalLessonPerWeeks * 100;


        if(i === this.listSubject.length - 1){
          return;
        }
        else if(i === 0){
          lastSubject.lessonPerWeeks = 36; 

        }
        lastSubject.lessonPerWeeks -= subject.lessonPerWeeks;
      }

    });}

And the HTML

<div *ngFor="let subject of listSubject">
<input *ngIf="subject.name != 'Remains'" type="number" [(ngModel)]="subject.lessonsPerWeeks" [formControl]="subject.changeValue">
<div *ngIf="subject.name === 'Remain'">
   {{subject.lessonPerWeeks}}
</div>
</div>

However, is there any better solution?

TheRemjx
  • 105
  • 1
  • 6