Search code examples
angularangular-formsangular-formbuilder

formgroupname have same index in ngfor


I have created a formarray that allows me to add several fields with the same name but different values but the problem is that when I fill a field the others with the same name are filled automatically . it like is always in the index 0 and don"t loop with *ngfor.

   actions: FormGroup;
constructor(private formBuilder: FormBuilder) {
      this.actions = this.formBuilder.group({
        acts: this.formBuilder.array([]) ,
      });
    }
acts() : FormArray {
  return this.actions.get("acts") as FormArray
}
newActs(): FormGroup {
  return this.formBuilder.group({
    n_action: new FormControl('',[Validators.required]),
    action_libel:new FormControl('',[Validators.required]),
    
  })
}
addaction() {
  this.acts().push(this.newActs());
}
removeAct(i:number) {
  this.acts().removeAt(i);
  console.log("this is ",i)
}
<button type="button" (click)="addaction()" class="btn btn-primary">
    <mat-icon>add_circle_outline</mat-icon>
  </button>
  <div class=" form-group" formArrayName="acts">
   
<div [formGroupName]="i" *ngFor="let action of acts().controls; let i=index">
    <div class="row">
    <div class="form-group">
      <label for="name">Action N°:</label>
      <input type="text" class="form-control" formControlName="n_action" id="n_action"  required [(ngModel)]="analysefnc.n_action" name="n_action">
      <span *ngIf="action.controls.n_action.errors?.required">required</span>

    </div>
    <div class="form-group">
      <label for="name">Action:</label>
      <input type="text" class="form-control" formControlName="action_libel" id="action_libel"  required [(ngModel)]="analysefnc.action_libel" name="action_libel">
      <span *ngIf="action.controls.action_libel.errors?.required">required</span>

    </div>
   
  </div>


Solution

  • You are binding to [formGroupName]='i' before you declare i

    Change your HTML to

    <div *ngFor="let action of acts().controls; let i=index" [formGroupName]="i">
    
        <!-- Other code here -->
       
      </div>
    

    Edit

    For the new error you may need to change acts() to a getter e.g

       actions: FormGroup;
       constructor(private formBuilder: FormBuilder) {
          this.actions = this.formBuilder.group({
            acts: this.formBuilder.array([]) ,
          });
        }
       get acts() : FormArray {
         return this.actions.get("acts") as FormArray
       }
       newActs(): FormGroup {
         return this.formBuilder.group({
            n_action: new FormControl('',[Validators.required]),
            action_libel:new FormControl('',[Validators.required]),
        
        })
    }
    addaction() {
      this.acts.push(this.newActs());
    }
    removeAct(i:number) {
      this.acts.removeAt(i);
      console.log("this is ",i)
    }
    
    

    and in the HTML

      <button type="button" (click)="addaction()" class="btn btn-primary">
        <mat-icon>add_circle_outline</mat-icon>
      </button>
      <div class=" form-group" formArrayName="acts">
        <div *ngFor="let action of acts.controls; let i=index" [formGroupName]="i">
          <div class="row">
            <div class="form-group">
              <label for="name">Action N°:</label>
              <input
                type="text"
                class="form-control"
                formControlName="n_action"
                id="n_action"
                required
                name="n_action"
              />
              <span *ngIf="action.get('n_action').errors?.required">required</span>
            </div>
            <div class="form-group">
              <label for="name">Action:</label>
              <input
                type="text"
                class="form-control"
                formControlName="action_libel"
                id="action_libel"
                required
                name="action_libel"
              />
              <span *ngIf="action.get('action_libel').errors?.required"
                >required</span
              >
            </div>
          </div>
        </div>
      </div>
    

    See this demo