Angular: json to formBuilder to json

随声附和 提交于 2021-02-10 20:31:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!