问题
From my server I am receiving a json that contains questions and different options:
[
{"description":"what is a color","questionID":"1","options":[{"response":"blue","optionID":"1"},{"response":"red","optionID":"2"},{"response":"football","optionID":"3"}]},
{"description":"what is a sport","questionID":"2","options":[{"response":"working","optionID":"4"},{"response":"playing","optionID":"5"},{"response":"dad","optionID":"6"},{"response":"chess","optionID":"7"}]}
]
With the formbuilder I created a form for this:
If I press submit I would like to send this json to my server:
{
"answers": [{"questionID":"1", "selectedoptionIDS":[{"selectedOptionID":"2"}]},
{"questionID":"2", "selectedoptionIDS":[{"selectedOptionID":"1"},{"selectedOptionID":"3"}]}
],
"email": "test@test.com"
}
I know how I can build my form with the formbuilder but when I press submit I am having troubles with responding the right JSON. Certainly because I can not work with this checkboxes. Can somebody help me with this?
Html page
<form [formGroup]="examForm" (ngSubmit)="onSubmit(examForm.value)">
<div formArrayName="answers">
<div *ngFor="let question of questions; let i=index">
<label>{{i+1}}) {{question.description}}</label>
<br />
<div *ngFor="let response of question.options">
<input type="checkbox" value="response.optionID" />
{{response.response}}
</div>
</div>
</div>
<label>Email:</label>
<input class="form-control" id="email" type="text" formControlName="email">
<div class="block-content block-content-full block-content-sm bg-body-light font-size-sm">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</form>
TS Page
import { Component, OnInit } from '@angular/core';
import { ExamSimulatorService } from '../services/exam-simulator.service';
import { ActivatedRoute } from '@angular/router';
import { FormBuilder, FormArray } from '@angular/forms';
@Component({
selector: 'app-exam',
templateUrl: './exam.component.html'
})
export class ExamComponent implements OnInit {
software;
questions;
examForm;
constructor(
private examSimulatorService: ExamSimulatorService,
private formBuilder: FormBuilder
) {
this.examForm = this.formBuilder.group({
email: "",
answers: this.formBuilder.array([
this.initAnswer()])
})
}
buildForm() {
for (var i = 0; i < this.questions.length() + 1; i++) {
this.addAnswer();
}
}
initAnswer() {
return this.formBuilder.group({
questionID: "",
selectedOptionIDs: this.formBuilder.array([
this.initOptions()
])
})
}
initOptions() {
return this.formBuilder.group({
selectedOptionID: ""
})
}
addAnswer() {
const answers = <FormArray>this.examForm["controls"]["answers"];
answers.push(this.initAnswer())
console.log(this.examForm);
}
addOption(i) {
const options = <FormArray>this.examForm["controls"]["answers"]["controls"][i]["controls"]["selectedOptionIDs"]
options.push(this.initOptions())
}
ngOnInit() {
this.activatedRoute.paramMap
.subscribe(params => {
this.software = params['params']['software'];
this.examSimulatorService.getExam(this.software).subscribe(response =>
this.questions = response["questions"]["questionList"]);
})
setTimeout(() => this.buildForm(), 200)
}
onSubmit(values) {
//this.examSimulatorService.addQuestion(values).subscribe(
// (responses) => {
// console.log(responses);
// });
//this.options.clear();
console.log(values);
}
}
回答1:
Instead of using your own model you can use full help from the Reactive form. The final model is not exactly you required but you can make workaround from it. You can see the working example at here https://stackblitz.com/edit/angular-1gtfmf
Component
export class ExamComponent implements OnInit {
@Input() name: string;
questionsList;
examForm: FormGroup;
dataModel: any; //active model
constructor(
private examSimulatorService: QuestionService,
private formBuilder: FormBuilder
) { }
get question(): FormGroup {
return this.formBuilder.group(
{
questionID: "",
description: "",
options: this.formBuilder.array([])
}
);
}
get option(): FormGroup {
return this.formBuilder.group({
optionID: "",
response: "",
selected: false
});
}
ngOnInit() {
this.dataModel = Object.create(null);
this.examForm = this.formBuilder.group({
email: ['', [Validators.required]],
questions: this.formBuilder.array([])
});
this.examSimulatorService.getAllQuestion().subscribe(response => {
this.questionsList = response.data;
this.loadForm(this.questionsList);
console.log(this.questionsList);
});
this.examForm.valueChanges.subscribe(data => {
this.dataModel = data;
});
}
loadForm(data) {
for (let ques = 0; ques < data.length; ques++) {
const questionsFormArray = this.examForm.get("questions") as FormArray;
questionsFormArray.push(this.question);
for (let opt = 0; opt < data[ques].options.length; opt++) {
const optionsFormsArray = questionsFormArray.at(ques).get("options") as FormArray;
optionsFormsArray.push(this.option);
}
}
this.examForm.controls.questions.patchValue(data);
}
showSavedValue() {
return this.dataModel;
}
showValue() {
return this.examForm.getRawValue();
}
onSubmit(values) {
console.log(values);
}
}
Html
<form [formGroup]="examForm" (ngSubmit)="onSubmit(examForm.value)">
<div>
<label>Email:</label>
<input class="form-control" id="email" type="text" formControlName="email">
</div>
<div formArrayName="questions">
<div *ngFor="let question of examForm.get('questions').controls;let questionIndex=index" [formGroupName]="questionIndex">
<label>{{questionIndex+1}} </label> {{examForm.value.questions[questionIndex].description}}
<div formArrayName="options">
<div *ngFor="let option of question.get('options').controls; let optionIndex=index" [formGroupName]="optionIndex">
<input type="checkbox" formControlName="selected" value="" /> {{examForm.value.questions[questionIndex].options[optionIndex].response}}
</div>
</div>
</div>
<div class="block-content block-content-full block-content-sm bg-body-light font-size-sm">
<button class="btn btn-primary" type="submit">Submit</button>
</div>
</div>
</form>
<pre> {{showSavedValue() | json }}
<pre>{{showValue() | json}}</pre>
来源:https://stackoverflow.com/questions/59036037/angular-json-to-formbuilder-to-json