I'm developing a feedback form in Angular using reactive forms approach. The response from the server has questions array which in turn has answers array.
Here is the response.
value": [
{
"description": "why didn't you turn up"
"answers": [
{
"description": "Unexpected Personal Committment"
},
{
"description": "Unexpected Official Work"
},
{
"description": "Even Not What I Expected"
},
{
"description": "Did Not Receive Further Information About The Event"
},
{
"description": "Incorrectly Registered"
},
{
"description": "Do Not Wish to Disclose"
}
]
}
]
I'm trying to build reactive form as follows.
ngOnInit() {
this.feedbackForm = this.fb.group({
questions: this.initQuestion()
})
}
initQuestion() {
return this.fb.group({
description: [],
answers: this.initAnswer()
})
}
initAnswer() {
return this.fb.group({
description: this.fb.array([])
})
}
How to map the question and response to my reactive form.
I tried as follows, but never works,
get questions(): FormArray {
return <FormArray>this.feedbackForm.get('questions');
}
get answers(): FormArray {
return <FormArray>this.feedbackForm.get('questions').get('answers');
}
displayQuestions(questions: Response<Question[]>): void {
if (this.feedbackForm) {
this.feedbackForm.reset();
}
this.questionsResponse = questions;
if (this.questionsResponse.value.length > 0) {
this.feedbackForm.setControl('questions', this.fb.array(this.questionsResponse.value || []));
this.feedbackForm.setControl('answers', this.fb.array(this.questionsResponse.value.answers || []));
}
}
Here is my template
<form [formGroup]="feedbackForm" novalidate (ngSubmit)="send()">
<div formArray="questions">
<div [formGroup]="i" *ngFor="let question of feedbackForm.controls.questions.controls; let i=index;">
<p>{{question.description}}</p>
<div formArray="answers">
<div [formGroup]="j" *ngFor="let answer of question.controls.answers.controls; let j=index">
<label [attr.for]="j">{{answer.description}}</label>
<input type="radio" [id]="j" [formControlName]="j" value="{{answer.descripiton}}" />
</div>
</div>
</div>
</div>
<input type="submit" value="Send">
I'm trying to display question with answers and I need user to select answer for the question and on submit I need the selected answer values.
Abdul you has two differents things:
but you are not defined your form. For this, you need know how is the data you want to send to the server. I must supouse you want send to the server some like
[1,3,1]
//or
[{question:1,answer:1},{question:2,answer:3},{question:3,answer:1}]
//or
[
{question:'why didn't you turn up',answer:'Unexpected Official Work'},
{question:'why didn't you do down',answer:'I don't know'}
]
As you can see, anyway you only need a unique formArray, you use the response of server to create the view of the form, but not the formArray
What do you want to send to the server?
Well, if we choose the third option is an FormArray, not a formGroup. Don't take care about it. A FormArray can be mannage like a FormGroup. First we are going to see how create the form Array
ngOnInit() {
this.feedbackForm = new FormArray(this.data.map(x=>new FormGroup({
'question':new FormControl(x.description),
'answer':new FormControl('')
})))
}
See that feedbackform is a Form Array. How create it? with each question, create a formGroup with two Form controls, question and answer
The .html becomes like
<form *ngIf="feedbackForm" [formGroup]="feedbackForm" (submit)="send()">
<div *ngFor="let control of feedbackForm.controls;let i=index" >
<div [formGroup]="control">
<input formControlName="question">
<div *ngFor="let a of data[i].answers">
<label>
<input type="radio" [value]="a.description" formControlName="answer">
<span>{{a.description}}</span>
</label>
</div>
</div>
</div>
<button type="submit">submit</button>
</form>
<pre> {{feedbackForm?.value | json}} </pre>
See that, we use the "data" to show the label of the radios and to give value to the radios, but the Form is only a form array. If our "data" have an "id" to the question and to the answer, we could use it
See the stackblitz
NOTE: I just add in the stackblitz a typical FormGroup with a FormArray because it's different the .html