0

On API call I have an Array of questions and their options JSON.

 [
  {
    "QuestionText": "Question goes here...",
    "AnswerChoice": [
      {
        "text": "text1",
        "answerId": "1"
      },
      {
        "text": "text2",
        "answerId": "2"
      },
      {
        "text": "text3",
        "answerId": "3"
      },
      {
        "text": "text4",
        "answerId": "4"
      },
      {
        "text": "text5",
        "answerId": "5"
      }
    ],
    "questionId": "1"
  },
  {
    "QuestionText": "Second question goes here...?",
    "AnswerChoice": [
      {
        "text": "text1",
        "answerId": "1"
      },
      {
        "text": "text2",
        "answerId": "2"
      },
      {
        "text": "text3",
        "answerId": "3"
      },
      {
        "text": "text4",
        "answerId": "4"
      },
      {
        "text": "text5",
        "answerId": "5"
      }
    ],
    "questionId": "2"
  }
  ... and so on.
]

Answer choices are radio buttons in UI.

So, now the question.

I am trying to build a Reactive Form for this problem. I am not able to come up with a solution. I am trying to build nested FormArrays but in vain.

My attempts to solve this problem:

HTML -

        <form [formGroup]="eidFormSubmission">
        <div>
            <div *ngFor="let question of questions; let i = index">
                <p>
                    {{i+1}}. {{question.QuestionText}}
                </p>
                <div class="form-group">
                    <div>
                        <div class="custom-control custom-radio"
                            *ngFor="let answer of question.AnswerChoice let k=index">
                            {{question.questionId}}
                            <input [value]="answer.answerId" type="radio" formControlName="i"
                                id="{{question.questionId}}" name="quesAnswer"
                                class="custom-control-input">
                            <label class="custom-control-label" for="{{question.questionId}}">
                                {{ answer.text }}</label>
                        </div>
                    </div>
                </div>
            </div>
        </div>
        <button (click)="onSubmitAnswers()" class="btn btn-primary">Next</button>
    </form>

TS -

  eidFormSubmissionInit(){
    const formArray = this.formBuilder.array([]);
    this.eidFormSubmission = this.formBuilder.group({
      questions: formArray
    })
  }

Now I am confused about how to push dynamically (after API response) into formbuilder.

And second problem is with the radio button when I select an option from the second question it deselects from the first question.

Any help would be appreciated!

1
  • Try to create a stackblitz example to help you. Commented Mar 19, 2020 at 20:15

1 Answer 1

1

Check this:

First create a form like this with "questions" inside as a FormArray:

this.eidFormSubmission = this.fb.group({
  questions: this.fb.array([])
});

after in your ngOnInit when your receive questions, loop through each question and add a new item into "questions" formArray

  ngOnInit() {
    this.dataService.getQuestions().subscribe((data: any[]) => {
      console.log(data);
      this.questions = data;

      this.questions.forEach(question => {
        (this.eidFormSubmission.get('questions') as FormArray).push(this.addQuestionFormGroup(question));
      });
    });
  }

with this utility function:

  private addQuestionFormGroup(question: any): FormGroup {
    return this.fb.group({
      QuestionText: question.QuestionText,
      AnswerChoice: new FormControl()
    });
  }

html markup:

<form (ngSubmit)="onSubmitAnswers()" [formGroup]="eidFormSubmission">
  <table>
    <tr formArrayName="questions" *ngFor="let data of eidFormSubmission.get('questions').controls; let i = index">
      <ng-container [formGroupName]="i">
        <th>
          <input type="text" formControlName="QuestionText" readonly>
        </th>
        <th *ngFor="let answer of questions[i].AnswerChoice">
          <input type="radio" formControlName="AnswerChoice" value="{{answer.answerId}}">{{answer.text}}
        </th>
      </ng-container>
    </tr>
  </table>
  <br>
  <button type="submit">Submit</button>
</form>

Working stackblitz

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks for the self-explanatory answer, it also helps me clear my basic concept about ng forms.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.