Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using ngFor with ngModel dynamic data wrong behaviour

I have complex and probably rookie bug in logic of my application, so I'll try to give comprehensive amount of information.

I have registration form binded to my data model. Phone number fields can be added by user during registration and saved as array.

My model:

export class RegistrationFormModel {
  //
  //
    Phones: Array<{Phone: string;}>;
  //
  //
}

And representation of this part of form

     <ion-item *ngFor="let Phone of regModel.Phones; let i = index">

        <ion-label floating>Phone number*</ion-label>
        <ion-input type="tel" required [(ngModel)]="regModel.Phones[i].Phone" name="Phone" #Phone="ngModel"
                   pattern="\d{10}"></ion-input>
        <ion-icon *ngIf="i==0" name="ios-add-circle-outline" item-right no-padding
                  (click)="addPhone()"></ion-icon>
        <ion-icon *ngIf="i!=0" name="ios-remove-circle-outline" item-right no-padding
                  (click)="removePhone(i)"></ion-icon>

     </ion-item>

My methods for adding and removing phones. I added logs and incremental index for debug purposes:

debugIndex = 0;
 \\
 \\
  addPhone() {
    console.log('phones before add: ' + JSON.stringify(this.regModel.Phones));
    this.regModel.Phones.splice((this.regModel.Phones.length), 0, {Phone: '' + this.debugIndex++});
    console.log('phones after add: ' + JSON.stringify(this.regModel.Phones));
  }

  removePhone(i: number) {
    console.log('phones before delete: ' + JSON.stringify(this.regModel.Phones));
    this.regModel.Phones.splice(i, 1);
    console.log('phones after delete: ' + JSON.stringify(this.regModel.Phones));
  }

And from this part strange things happen. According to logs data writes in my model properly but in UI last element replaces everything in input fields. But after removing one of the phones displayed phones for this moment seems like represent last state of UI.

enter image description here

My logs captured during recording:

 "phones before add: [{"Phone":"123456789"}]", 
  "phones after add: [{"Phone":"123456789"},{"Phone":"0"}]", 
  "phones before add: [{"Phone":"123456789"},{"Phone":"4567890"}]", 
  "phones after add: [{"Phone":"123456789"},{"Phone":"4567890"},{"Phone":"1"}]", 
  "phones before delete: [{"Phone":"123456789"},{"Phone":"4567890"},{"Phone":"1"}]", 
  "phones after delete: [{"Phone":"123456789"},{"Phone":"4567890"}]", 
  "phones before add: [{"Phone":"123456789"},{"Phone":"4567890"}]", 
  "phones after add: [{"Phone":"123456789"},{"Phone":"4567890"},{"Phone":"2"}]", 
  "phones before add: [{"Phone":"123456"},{"Phone":"4567890"},{"Phone":"2"}]", 
  "phones after add: [{"Phone":"123456"},{"Phone":"4567890"},{"Phone":"2"},{"Phone":"3"}]", 
  "phones before add: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"2"},{"Phone":"3"}]", 
  "phones after add: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"2"},{"Phone":"3"},{"Phone":"4"}]", 
  "phones before delete: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"2"},{"Phone":"3"},{"Phone":"4"}]"
  "phones after delete: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"2"},{"Phone":"4"}]", 
  "phones before add: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"47890"},{"Phone":"4"}]", 
  "phones after add: [{"Phone":"123456"},{"Phone":"456789"},{"Phone":"47890"},{"Phone":"4"},{"Phone":"5"}]"

Any help appreciated and thanks in advance.

like image 291
Autumn_Cat Avatar asked Dec 21 '16 15:12

Autumn_Cat


1 Answers

Adding [ngModelOptions]="{standalone: true}" to your input should fix the problem:

<ion-input type="tel" required [(ngModel)]="regModel.Phones[i].Phone" 
[ngModelOptions]="{standalone: true} #Phone="ngModel" pattern="\d{10}">
</ion-input>

For every input with NgModel directive, FormControl will be created and it will be added to FormGroup, but when you add standalone: true, the fields won't be added to the FormGroup and this problem should be fixed. You should also remove name attribute from your input because only one of those is needed when using template driven forms. (name or standalone: true)

like image 98
Stefan Svrkota Avatar answered Oct 23 '22 03:10

Stefan Svrkota