angularformsinputangular-ngmodelangular-template-form

angular dynamic input populates same value


Im trying to build a form wherein you can create another field of input on clicking an add button. The problem is that same value gets populated for each row input. As you can see from the below image, each row gets the same value. I think it is because of the ngmodel. Or maybe something else. How to resolve this?

image enter image description here

html

   <div class="row mt-2 " *ngFor="let auditField of dynamicAuditField; let i = index;">
        <div class="col-md">
           <select class="form-control dynamic-input form-input p-0 pl-2"
              id="criteria" #criteria="ngModel" [(ngModel)]="addmodel.criteria"
              name="criteria_{{auditField.id}}">
                <option [value]='null' disabled>Select Criteria</option>
                <option *ngFor="let data of auditField.criteria" [value]="data.value"> 
            {{data.name}}</option>
           </select>
       </div>

       <div class="col-md">
        <select class="form-control dynamic-input form-input p-0 pl-2" id="condition" #condition="ngModel" 
         [(ngModel)]="addmodel.condition" name="condition_{{auditField.id}}">
         <option [value]='null' disabled>Select Condition</option>
         <option *ngFor="let data of auditField.condition" [value]="data.value">{{data.name}}</option>
        </select>
       </div>

       <div class="col-md">
          <input type="text" class="form-control dynamic-input form-input p-0 pl-2" 
            #value="ngModel" [(ngModel)]="addmodel.value" name="value_{{auditField.id}}">
       </div>
       <div>
         <i class="fa fa-trash-o input-row-delete" aria-hidden="true (click)="removeField(i)"></i>
       </div>
     </div>

ts

public dynamicAuditField: any[] = [{
id: 1,
criteria: [
  {
    name: "Process 1",
    value: "process_1"
  },
  {
    name: "Process 2",
    value: "process_2"
  },
  {
    name: "Process 3",
    value: "process_3"
  },
],
condition: [
  {
    name: "Sub Process 1",
    value: "sub_process_1"
  },
  {
    name: "Sub Process 2",
    value: "sub_process_2"
  },
  {
    name: "Sub Process 3",
    value: "sub_process_3"
  },
],
value: ''
}];

addField(){
this.dynamicAuditField.push({
  id: this.dynamicAuditField.length + 1,
  criteria: [
    {
      name: "Process 1",
      value: "process_1"
    },
    {
      name: "Process 2",
      value: "process_2"
    },
    {
      name: "Process 3",
      value: "process_3"
    },
  ],
  condition: [
    {
      name: "Sub Process 1",
      value: "sub_process_1"
    },
    {
      name: "Sub Process 2",
      value: "sub_process_2"
    },
    {
      name: "Sub Process 3",
      value: "sub_process_3"
    },
  ],
  value: ''
})
}

Solution

  • Since you are adding fields dynamically, you need to define proper type of model to hold the data. Though the type of addmodel is not shared in question, it seems to be an object, but what you really would need is an array to hold multiple values corresponding to form controls.

    With the current code logic, you are binding multiple form controls to the same model value, and hence same data gets populated. Try defining addmodel as an array of object, and that should resolve the issue. Below snippets should help you to fix the issue.

    The initial addmodel should be something as:

    // Please handle the types and data as per your logic
    // Important point to note is that it should be an array with one element(an object)
    addmodel: any = [{}];
    

    In the html file you would need to change the [(ngModel)] to:

    [(ngModel)]="addmodel[i].criteria"
    [(ngModel)]="addmodel[i].condition"
    [(ngModel)]="addmodel[i].value"
    

    Also you would need to take care of updating the addmodel while calling addField() and removeField(i):

    addField() {
     this.addmodel.push({}); // Add new record
     ...
    }
    
    removeField(i: number) {
     // remove relevant record from this.addmodel
     ...
    }