Firstly sorry for creating a long post but I had no option other than this as I need to explain where am facing issue.
I have a form where a control is an array of JSON. I've created a reactive form wrt that. Below is my JSON and my TS code:
JSON (got from backend request)
{
"questionList": [
{
"questionCategory": {
"questionCategoryName": "JAVA",
"id": 40,
"isActive": true,
"timestamp": "2020-06-12 14:06:47.325"
},
"difficultyLevel": 0,
"options": [
{
"answer": false,
"id": 2,
"optionText": "method",
"timestamp": "2020-06-18 17:17:11.75"
},
{
"answer": false,
"id": 3,
"optionText": "name",
"timestamp": "2020-06-18 17:17:11.753"
},
{
"answer": false,
"id": 4,
"optionText": "class",
"timestamp": "2020-06-18 17:17:11.758"
},
{
"answer": true,
"id": 1,
"optionText": "variable",
"timestamp": "2020-06-18 17:17:11.663"
}
],
"section": {
"marksPerQuestion": 3,
"id": 8,
"isActive": true
},
"id": 1,
"isActive": true,
"questionText": "What is a variable ?",
"timestamp": "2020-06-18 17:17:10.946"
},
{
"questionCategory": {
"questionCategoryName": "APTITUDE",
"id": 41,
"isActive": true
},
"difficultyLevel": 0,
"options": [
{
"answer": true,
"id": 6,
"optionText": "xyz",
"timestamp": "2020-06-17 21:50:48.975"
},
{
"answer": true,
"id": 5,
"optionText": "abc",
"timestamp": "2020-06-17 21:50:48.907"
}
],
"section": {
"marksPerQuestion": 2,
"id": 7,
"isActive": true,
"timestamp": "2020-06-12 14:08:14.181"
},
"id": 2,
"isActive": true,
"questionText": "What is def",
"timestamp": "2020-06-17 21:50:48.6"
}
],
"empty": false
}
TS Code for this JSON
updateQuestionForm = this.fb.group({
id: [], isActive: [], difficultyLevel: [0], questionText: [''],
questionCategory: this.fb.group({
id: [],
questionCategoryName: ['']
}),
section: this.fb.group({
id: [],
marksPerQuestion: ['']
}),
options: new FormArray([])
});
optionForm = this.fb.group({
id: [], optionText: [''], answer: []
});
onEdit(e) {
const formArray: FormArray = this.updateQuestionForm.get('options') as FormArray;
this.updateQuestionForm.controls['id'].setValue(e.id);
this.updateQuestionForm.controls['isActive'].setValue(e.isActive);
this.updateQuestionForm.controls['questionText'].setValue(e.questionText);
this.updateQuestionForm.controls['questionCategory'].setValue({
id: e.questionCategory.id,
questionCategoryName: e.questionCategory.questionCategoryName
});
this.updateQuestionForm.controls['section'].setValue({
id: e.section.id,
marksPerQuestion: e.section.marksPerQuestion
});
for(let i of e.options) {
this.optionForm.controls['id'].setValue(i.id);
this.optionForm.controls['optionText'].setValue(i.optionText);
this.optionForm.controls['answer'].setValue(i.answer);
formArray.push(new FormControl(this.optionForm.value));
}
console.log(this.updateQuestionForm.value);
}
get Status() {
return this.updateQuestionForm.get('isActive');
}
get Options(): FormArray {
return this.updateQuestionForm.get('options') as FormArray;
}
Let me explain what the TS states:
Firstly, I am creating a form of updateQuestionForm which is the main form for the JSON.
The second form of optionForm is for the options FormArray of updateQuestionForm.
I've created this second form because I need certain controls from the array. So this stuck in my mind.
The onEdit() method is triggered by a button click which fetches the JSON from a Mat-Table.
The HTML form
<form [formGroup]="updateQuestionForm" (submit)="onUpdateQuestionForm()">
<div class="row">
<div class="col-md-4">
<mat-form-field>
<mat-label>Enter Question</mat-label>
<input matInput formControlName="questionText">
</mat-form-field>
</div>
<div class="col-md-3">
<mat-form-field formGroupName="questionCategory">
<mat-label>Question Category</mat-label>
<mat-select formControlName="id">
<ng-container *ngFor="let q of QuestionCategory;">
<mat-option [value]="q.id">{{ q.questionCategoryName }}</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
</div>
<div class="col-md-3">
<mat-form-field formGroupName="section">
<mat-label>Marks</mat-label>
<mat-select formControlName="id">
<ng-container *ngFor="let m of Marks;">
<mat-option [value]="m.id">{{ m.marksPerQuestion }}</mat-option>
</ng-container>
</mat-select>
</mat-form-field>
</div>
<div class="col-md-2">
<mat-label>Status</mat-label><br>
<mat-slide-toggle color="primary" formControlName="isActive">{{ Status ? 'Active' : 'Inactive' }}</mat-slide-toggle>
</div>
</div>
<h3>Options & Answers</h3>
<div formArrayName="options">
<div class="row" *ngFor="let o of Options.value; index as i" [formGroupName]="i">
<div class="col-md-6">
<mat-form-field>
<mat-label>Option</mat-label>
<input matInput formControlName="optionText">
</mat-form-field>
</div>
<div class="col-md-3">
<mat-label>Answer</mat-label><br>
<mat-slide-toggle color="primary" formControlName="answer">
{{ answer ? 'True' : 'False' }}
</mat-slide-toggle>
</div>
</div>
</div>
<button mat-flat-button type="submit" style="background-color: #28a745; color: white;">Update</button>
</form>
This is the form of the JSON. I'm successfully able to fetch and store the value for the controls questionCategory, section, isActive, questionText. The problem is occurring for the options control. There I have 4 options (with 4 optionText, 4 answer each fetched from the database; refer the sample JSON above).
But I am not able to display the controls. Looks like the ngFor inside formArrayName="options" is not working. After the h2, nothing is coming.
Please help me. FYI I was following this link for the formArrayName looping part.

updateQuestionFormyou are trying to create the JSON structure you have mentioned above? Or are you trying to take answers from the user for the given questions list?onEdit()method is fetching values and initializing it in theupdateQuestionFormcontrols. These values will be retrieved in the view part with the controls. And then if the value gets changed theUpdatebutton will send the values to the backend which I'll integrate later for timing I need the options to get rendered to view.optionForm.