'How to save Dynamic Form Answer in Angular?

I'm trying to save some data that I display dynamic in the browser.This is my HTML where I iterate trough a list of exam questions dragged from the database and display them dynamic in browser.

<div mat-dialog-content [formGroup]="examform">
    <div *ngFor="let exam_question of exam_questions;let i = index">
          <mat-label >{{exam_question.questionTitle}}</mat-label><br>
          <mat-radio-group aria-label="Image Position">
         <mat-radio-button  id="{{'examItem1'+i}}" value="1" >{{exam_question.questionItem1}}</mat-radio-button>
          <mat-radio-button  id="{{'examItem2'+i}}" value="2">{{exam_question.questionItem2}}</mat-radio-button>
          <mat-radio-button id="{{'examItem3'+i}}" value="3">{{exam_question.questionItem3}}</mat-radio-button>
          <mat-radio-button  id="{{'examItem4'+i}}" value="4">{{exam_question.questionItem4}}</mat-radio-button>
        </mat-radio-group> 
      </div>
<div>
    <button class="button-course" mat-raised-button color="primary" (click)="submitAnswer()">Submit</button>
 

How can I use Form from Angular Typescript to save what the user responds to this form? For example what was the answer for the first question, for the second question and so on. I tried to put on every Form Controls and id, but I don t know how to go further.This is the form from Typescript.

import { registerLocaleData } from '@angular/common';
import { Component, OnInit } from '@angular/core';
import { FormArray, FormBuilder, FormControl, FormGroup, Validators } from '@angular/forms';
import { ActivatedRoute, Router } from '@angular/router';
import { Questions } from '../models/questions';
import { SharedService } from '../service/shared.service';

@Component({
  selector: 'app-quiz-exam-page',
  templateUrl: './quiz-exam-page.component.html',
  styleUrls: ['./quiz-exam-page.component.css']
})
export class QuizExamPageComponent implements OnInit {
  examID:any;
  examform!: FormGroup;
  examData: any;
  userDetails:any;
  examFormArray=new FormArray([new FormControl('',Validators.required)]);
  constructor(private formBuilder:FormBuilder,private router:Router,private sharedService:SharedService,private route:ActivatedRoute) { }
  exam_questions:Questions[]=[];
  ngOnInit(): void {
    this.route.queryParams
      .subscribe(params => {
        this.examID = params['examID'];
      }
    );
  
    this.examform=this.formBuilder.group({
      examTitle:this.formBuilder.array([],Validators.required),
      examItem1:this.formBuilder.array([],Validators.required),
      examItem2:this.formBuilder.array([],Validators.required),
      examItem3:this.formBuilder.array([],Validators.required),
      examItem4:this.formBuilder.array([],Validators.required)
    });
    if(localStorage.getItem('token')==null)
      this.router.navigate(['login'])
    this.sharedService.getUserProfile().subscribe(res=>{
        this.userDetails=res;
        this.sharedService.getExamQuestionsByID(this.examID).subscribe(data=>{
          this.exam_questions=data;
      },err=>{
        console.log(err)
      });
       },(err:any)=>{
         console.log(err);
       },
       );
    
    
  }
  submitAnswer(submitData:any)
  {
    this.examData = submitData;
    console.log(this.examData)

  }

}

This is the generated form. And as you can see, I need the answer for every question and after that I click submit, it will save the answer for every question, but I need to know to what question it was the answer, that is why I put the Id in the HTML.

This is my question array. It is an interface:

export interface Questions {
    questionID:number;
    questionCourseID:number;
    questionTitle:string;
    questionTopic:string;
    questionPoints:string;
    questionDifficulty:string;
    questionItem1:string;
    questionItem2:string;
    questionItem3:string;
    questionItem4:string;
    qustionAnswers:string;
}


Solution 1:[1]

To your HTML-File I would add an NgSubmit and also add the type submit to your button. In the ngSubmit you give the value of your form (examForm) to the function (saveForm) in the Typescript-File. Instead I would delete the (click) event on your button.

HTML-File

<div mat-dialog-content [formGroup]="examform" (ngSubmit)="saveForm(examform.value)">
    <div *ngFor="let exam_question of exam_questions;let i = index">
          <mat-label >{{exam_question.questionTitle}}</mat-label><br>
          <mat-radio-group aria-label="Image Position">
         <mat-radio-button  id="{{'examItem1'+i}}" value="1" >{{exam_question.questionItem1}}</mat-radio-button>
          <mat-radio-button  id="{{'examItem2'+i}}" value="2">{{exam_question.questionItem2}}</mat-radio-button>
          <mat-radio-button id="{{'examItem3'+i}}" value="3">{{exam_question.questionItem3}}</mat-radio-button>
          <mat-radio-button  id="{{'examItem4'+i}}" value="4">{{exam_question.questionItem4}}</mat-radio-button>
        </mat-radio-group> 
      </div>
<div>
<button type="submit" class="button-course" mat-raised-button color="primary">Submit</button>
 

If you want, that your button only is pressable if the inputs are valid (for example every required fields are filled out). You can add following code to your button:

<button [disabled]="!examForm?.valid" type="submit" class="button-course" mat-raised-button color="primary">Submit</button>

In your Typescript-File, you should write a function with the same name as you specified in (ngSubmit)="functionName". In my example, the function Name is saveData(). Then you write the value from the Form to a variable with the datatype any.

So your TS-File would look something like:

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl } from '@angular/forms';

@Component({
  selector: 'app-test',
  templateUrl: './test.component.html',
  styleUrls: ['./test.component.css']
})
export class TestComponent implements OnInit {
  examForm!: FormGroup;
  examData: any;

  constructor(
    private formBuilder: FormBuilder,
  ) { }

  ngOnInit(): void {
    this.examForm=this.formBuilder.group({
      examTitle:this.formBuilder.array([],Validators.required),
      examItem1:this.formBuilder.array([],Validators.required),
      examItem2:this.formBuilder.array([],Validators.required),
      examItem3:this.formBuilder.array([],Validators.required),
      examItem4:this.formBuilder.array([],Validators.required)
    });
  }

  showPreview(submitData: any) {
    this.examData = submitData;
    console.log(this.examData)
  }
  
}

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1