Search code examples
angularangular-reactive-formsformarray

Iterate over FormArray to show form fields


I'm trying to get something going with reactive forms but having difficulty achieving what I thought would be straightforward.

I would like to loop over elements and display them as form controls.

I currently have:

@Component({
  selector: 'app-reactive-form-test',
  styleUrls: ['./reactive-form-test.component.scss'],
  template: `
    <form [formGroup]="questionForm">
      <ng-container formArrayName="questions" *ngFor="let question of questionForm.controls; let i = index">
<input type="text" formControlName="i">
</ng-container>
    </form>
  `
})
export class ReactiveFormTestComponent implements OnInit {
  questionForm: FormGroup;

  questions: ScheduledQuestionInterface[];

  constructor(private fb: FormBuilder) { }

  ngOnInit(): void {
    this.questionForm = this.fb.group({
      questions: this.fb.array([])
    });
    this.questions = [];
    this.questions.push(new ScheduledQuestion(1, 1, 1, 1));
    this.questions.push(new ScheduledQuestion(2, 3, 1, 2));
    this.questions.push(new ScheduledQuestion(3, 4, 1, 3));
    this.questions.forEach(value => {
      const control = this.questionForm.get('questions') as FormArray;
      control.push(this.fb.group({
        id: [value.id],
        deliveryDateTime: [value.deliveryDateTime]
      }));
    });
  }
}

Right now I'm getting the below error:

Cannot find a differ supporting object '[object Object]' of type 'object'. NgFor only supports binding to Iterables such as Arrays..

What do I need to do to this code to simply show 3 text fields from the 3 ScheduledQuestion objects?


Solution

  • questionForm.controls is an Object with the keys as the formControls basically in your case

      {
         questions: []
      }
    

    You are trying to loop over the above object which is not iterable hence the error

    Below should work

    @Component({
      selector: 'app-reactive-form-test',
      styleUrls: ['./reactive-form-test.component.scss'],
      template: `
        <form [formGroup]="questionForm">
          <ng-container formArrayName="questions">
            <ng-container *ngFor="let question of questionControls.controls; let i = index">
    <input type="text" [formGroupName]="i">
          </ng-container>
          
    </ng-container>
        </form>
      `
    })
    export class ReactiveFormTestComponent implements OnInit {
      questionForm: FormGroup;
    
      questions: ScheduledQuestionInterface[];
      get questionControls() {
         return this.questionForm.get('questions') as FormArray;
      }
      
    
      constructor(private fb: FormBuilder) { }
    
      ngOnInit(): void {
        this.questionForm = this.fb.group({
          questions: this.fb.array([])
        });
        this.questions = [];
        this.questions.push(new ScheduledQuestion(1, 1, 1, 1));
        this.questions.push(new ScheduledQuestion(2, 3, 1, 2));
        this.questions.push(new ScheduledQuestion(3, 4, 1, 3));
        this.questions.forEach(value => {
          const control = this.questionForm.get('questions') as FormArray;
          control.push(this.fb.group({
            id: [value.id],
            deliveryDateTime: [value.deliveryDateTime]
          }));
        });
      }
    }