1

I have a form with a telephone field, when you click on the Add button, a new field will appear. What is happening is that when I click on Add, the value typed on the previous fields get reset. I managed to make it work by removing the "form" tags, but I need this form on my project. How can I make it work using "form"?

HTML

<form>
   <div *ngFor="let phonecount of phonecount; let i = index" class="form-group">
<label>Optional Phone </label>
<input type="text" class="form-control" [(ngModel)]="user.extraphones[i]" name="phone2">
 </div>
<input (click)="onSubmito()" type="submit" value="Add" class="btn btn-primary">
</form>

TS

user = {
          name:'',
          phone:'',
          extraphones:[]
      };
  namee='';
   phonecount:string[]=[''];
onSubmito(){
  this.phonecount.push(this.namee);
}

Punkler: https://plnkr.co/edit/i85x1m?p=preview

Cœur
  • 37,241
  • 25
  • 195
  • 267
Gustavo
  • 874
  • 4
  • 13
  • 27

1 Answers1

3

Make sure you're binding to the right thing. Similarly, make sure that a proper collection is being updated when use clicks "Add".

After understanding you problem better I found this SO answer and this GitHub issue.

Was able to fix your issue... Notice the following things:

  • trackBy:trackById in template and trackById function in typescript code.
  • name attribute on <input> field.

//our root app component
import {Component, NgModule, VERSION} from '@angular/core'
import {FormsModule} from '@angular/forms'
import {BrowserModule} from '@angular/platform-browser'

export class Info {
  id: number;
  description: string;
}

    @Component({
      selector: 'my-app',
      template: `
      <form>
       <div *ngFor="let ph of user.extraphones; let i = index; trackBy:trackByIndex" class="form-group">
        <label>Optional Phone</label>
        <input type="text" class="form-control"
          [(ngModel)]="user.extraphones[i]" name="item-{{i}}">
      </div>
      <input (click)="onSubmito()" type="submit" value="Add" class="btn btn-primary">
    </form>

      {{ user.extraphones | json }}
      `,
    })
    export class App {
      user = {
              id:'',
              _id:String,
              name:'',
              phone:'',
              extraphones:['123', '345', '678'],
              rank:''
          };

      namee='';

      onSubmito(){
        this.user.extraphones.push(this.namee);
      }

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

@NgModule({
  imports: [ BrowserModule, FormsModule ],
  declarations: [ App ],
  bootstrap: [ App ]
})
export class AppModule {}
Igor Soloydenko
  • 11,067
  • 11
  • 47
  • 90
  • I will try this. But wouldn't changing the input ngmodel to 'phone' makes it insert into phone property instead of extraphones? – Gustavo Oct 16 '17 at 00:27
  • @Gustavo I have modified both the template and the TS code so that it's easier for you to understand, what's going on. I also strongly recommend you using better names. – Igor Soloydenko Oct 16 '17 at 00:30
  • The array values sent on this form is not as expected. It's getting the 'namee' property value and adding to all array values except the first one (I'm sending this trough a REST API). I changed the namee value on TS to = 'somedata' to explain better. Here's what's happen when I send 3 fields with different values: extraphones:(3) ["", "somedata", "somedata"] – Gustavo Oct 16 '17 at 01:01
  • @Gustavo now I see shy. Storing phones as array of strings is a horrible idea for many reasons. One of them is that Angular will not be able to detect the changes (since string is a primitive type) unless we specially instruct it. Notice `name` attribute on `input` tag; and `trackById` function. Read about them to get a better idea about what's going on. – Igor Soloydenko Oct 16 '17 at 01:46
  • Hope I answered your question this time :) – Igor Soloydenko Oct 16 '17 at 01:47