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

3
  • edit your post, your markup has no link with ts code Commented Mar 20, 2017 at 6:37
  • @Aravind: Thank you for your remind. I have added typescript tag, is it ok? Commented Mar 20, 2017 at 6:40
  • your post has ts code and the variables are not in the markup your screenshot looks different Commented Mar 20, 2017 at 6:41

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

2 Comments

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.
Actually, I don't like to create different FormControl for each object in the list. But it's work perfect now. Thank you, Ghosh
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?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.