Input ngModel in *ngFor binds to same value for all inputs
Asked Answered
C

2

5
<tbody>
    <tr *ngFor="let trxList of trxNumberList; let i= index">
        <td>{{i}}</td>
        <td>
            <input type="text" name="trxNumber-{{i}}" class="form-control" minlength="1" maxlength="20" [(ngModel)]="trxList.trxNumber" />
        </td>
    </tr>
</tbody>

This is my table body, When I key in first input box, all the other inputs are binding to this value. Image attached. Please help.

enter image description here

EDIT:

Component code:

trxNumberObj = new Transaction;

ngOnInit() { 
  for(var i= 0 ; i <= 10; i++ ){ 
    this.trxNumberObj.count = i; 
    this.trxNumberList.push(this.trxNumberObj); 
  } 
}
Cheeky answered 9/8, 2017 at 16:11 Comment(7)
what does trxList and trxNumberList have.Not understanding why you are trying [(ngModel)]="trxList.trxNumber"/>. Can you attach the data as well.?Statant
sure .trxNumberList is a array of Transaction object.. which contains variables like transaction Number, name, comments etc.. trxNumberList : Transaction[] = []; and I need 10 rows so I created 10 objects and pushed it to a array list. trxNumberObj = new Transaction; ngOnInit() { for(var i= 0 ; i <= 10; i++ ){ this.trxNumberObj.count = i; this.trxNumberList.push(this.trxNumberObj); } }Cheeky
what do you want the ngModel equal to be ?the transaction number ?Statant
Yes, I want to enter 10 different transaction numbers in those input fields.Cheeky
@Raj, always add any additional info in the question instead of comment to make it more readable. This time I added the piece of code to your question. Also remember to add all related code in your original question. This piece of code you presented in comment was very crucial information for solving this problem ;)Cirilla
Sure @AJT_82, This was my first post in SO so not sure how it works. Will improve next time Thank you :)Cheeky
Yeah, no problem at all, I understand well that it is difficult to asses what is needed when you are new. We all have been there! :) Good luck and happy coding!Cirilla
C
4

Picked from your comment, the following piece of code:

trxNumberObj = new Transaction;

ngOnInit() { 
  for(var i= 0 ; i <= 10; i++ ){ 
    this.trxNumberObj.count = i; 
    this.trxNumberList.push(this.trxNumberObj); 
  } 
}

This behavior in template is because objects are mutable in JS. So what you are doing now, is pushing the same object to the array, which means that all objects in the array have a reference to the same object. What you need to do is to push new objects in the array:

ngOnInit() { 
  for(var i= 0 ; i <= 10; i++ ){ 
    this.trxNumberList.push({count:i++});  // push new object every time!
  }
}

You seem that you have a model for your object, so adapt that accordingly in above code.

Cirilla answered 9/8, 2017 at 19:26 Comment(1)
Yes you are right. I realized it before seeing this and got working. This is what I did. trxNumberObj : Transaction; ngOnInit() { for(var i= 0 ; i <= 10; i++ ){ this.trxNumberObj = new Transaction; this.trxNumberObj.count = i; this.trxNumberList.push(this.trxNumberObj); } } Thanks for the help :)Cheeky
S
5

Use the following

<input type="text" name="trxNumber-{{i}}" class="form-control" minlength="1" maxlength="20" [(ngModel)]="trxNumberList[index].trxNumber" />

This should do the trick.Let me know if it doesnt

Statant answered 9/8, 2017 at 17:50 Comment(8)
Nope, It dint work. This is my DOM <input _ngcontent-c10="" class="form-control ng-valid ng-dirty ng-touched" maxlength="20" minlength="1" type="text" ng-reflect-minlength="1" ng-reflect-maxlength="20" ng-reflect-name="trxNumber-0" ng-reflect-model="33">Cheeky
Updated my ans ..check.it ..dont copy paste,i am in phone,so not sure if the variable names are okayStatant
I tried this way, It's still not working. :( I tried all the possible cases, not sure what is the problem.. I'm not copy pasting..Cheeky
okay !just try <input type="text" name="trxNumber-{{i}}" class="form-control" minlength="1" maxlength="20" [(ngModel)]="trxNumber-{{i}}" /> ..This should work ,try this just to check,dont assume it to be the final solutionStatant
Nope ngModel dosent accept interpolation. Throws error: [ERROR ->][(ngModel)]="trxNumber-{{i}}"/>Cheeky
ma be create a simple plunker so that i can look at the exact issue !Statant
Thanks @vikk I got that working. Your suggestions make me think twice. Thanks for your time.. :)Cheeky
Works! Thanks a lot!Manna
C
4

Picked from your comment, the following piece of code:

trxNumberObj = new Transaction;

ngOnInit() { 
  for(var i= 0 ; i <= 10; i++ ){ 
    this.trxNumberObj.count = i; 
    this.trxNumberList.push(this.trxNumberObj); 
  } 
}

This behavior in template is because objects are mutable in JS. So what you are doing now, is pushing the same object to the array, which means that all objects in the array have a reference to the same object. What you need to do is to push new objects in the array:

ngOnInit() { 
  for(var i= 0 ; i <= 10; i++ ){ 
    this.trxNumberList.push({count:i++});  // push new object every time!
  }
}

You seem that you have a model for your object, so adapt that accordingly in above code.

Cirilla answered 9/8, 2017 at 19:26 Comment(1)
Yes you are right. I realized it before seeing this and got working. This is what I did. trxNumberObj : Transaction; ngOnInit() { for(var i= 0 ; i <= 10; i++ ){ this.trxNumberObj = new Transaction; this.trxNumberObj.count = i; this.trxNumberList.push(this.trxNumberObj); } } Thanks for the help :)Cheeky

© 2022 - 2024 — McMap. All rights reserved.