How to represent Array using fieldset in angular template driven form model?

This is how you can do it with FormArray

component

import { Component, OnInit } from "@angular/core";
import {
  Validators,
  FormBuilder,
  FormGroup,
  FormControl,
  FormArray
} from "@angular/forms";
@Component({
  ...
})
export class SurveyComponent implements OnInit {
  public surveyForm: FormGroup;

  constructor(protected formBuilder: FormBuilder) {}

  ngOnInit() {
    this.surveyForm = this.formBuilder.group({
      Survey: new FormGroup({
        Id: new FormControl("", Validators.required),
        Name: new FormControl("", Validators.required)
      }),
      QuestionAnswerSets: new FormArray([])
    });
  }

  initSet() {
    return this.formBuilder.group({
      Question: new FormControl("", Validators.required),
      Answers: new FormArray([])
    });
  }

  addSet() {
    const questionAnswerSets = <FormArray>(
      this.surveyForm.controls.QuestionAnswerSets
    );
    questionAnswerSets.push(this.initSet());
  }

  removeSet(setId: number) {
    let questionAnswerSets = <FormArray>(
      this.surveyForm.controls.QuestionAnswerSets
    );
    questionAnswerSets.removeAt(setId);
  }

  initAnswer() {
    return this.formBuilder.group({
      Answer: new FormControl("", Validators.required)
    });
  }

  addAnswer(setId: number) {
    const questionAnswerSets = <FormArray>(
      this.surveyForm.controls.QuestionAnswerSets
    );
    const answer = <FormArray>(
      questionAnswerSets.controls[setId]["controls"].Answers
    );
    answer.push(this.initAnswer());
  }

  removeAnswer(setId: number, answerId: number) {
    const questionAnswerSets = <FormArray>(
      this.surveyForm.controls.QuestionAnswerSets
    );
    const answer = <FormArray>(
      questionAnswerSets.controls[setId]["controls"].Answers
    );
    answer.removeAt(answerId);
  }
}

teamplate

<form [formGroup]="surveyForm" (ngSubmit)="saveForm(surveyForm.value)">
    <div formArrayName="QuestionAnswerSets">
        <fieldset *ngFor="let questionAnswerSet of surveyForm.controls.QuestionAnswerSets.controls; index as setId;" [formGroupName]="setId">
            <input type="text" formControlName="Question" />
            <div formArrayName="Answers">
                <div class="ui-g-12" *ngFor="let answer of this.surveyForm.controls.QuestionAnswerSets.controls[setId].controls.Answers.controls; index as answerId;"
                    [formGroupName]="answerId">
                    <input type="text" formControlName="Answer" />
                    <button type="button" (click)="removeAnswer(setId, answerId)">Remove Answer</button>
                </div>
            </div>
            <button type="button" (click)="addAnswer(setId)">Add Answer</button>
        </fieldset>
    </div>
    <button type="button" (click)="addSet()">Add Set</button>
</form>

Probably I've missed something, but it will give you an idea


After reading so many articles on nested models template driven forms and official angular documentation i could say this can not be done using template driven forms as there no directive which represents an array. (grouping as how fieldset does for an object with ngModelGroup)

This could be done with angular reactive forms with FormArrayName

https://angular.io/api/forms/FormArrayName

Tags:

Angular6