【问题标题】:How to map server response to angular Reactive Forms with nested form array如何使用嵌套表单数组将服务器响应映射到角度响应式表单
【发布时间】:2019-07-29 05:29:39
【问题描述】:

我正在使用响应式表单方法在 Angular 中开发反馈表单。 来自服务器的响应包含 questions 数组,而 questions 数组又包含 answers 数组。

这是回复。

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"
}
]
}
]

我正在尝试如下构建反应式表单。

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([])
    })
  }

如何将问题和响应映射到我的反应形式。

我尝试如下,但始终没有成功,

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 || []));
    }           
  }

这是我的模板

<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">

我正在尝试显示带有答案的问题,我需要用户为问题选择答案,并且在提交时我需要选择的答案值。

【问题讨论】:

  • 发布您的模板。你也可以做一个 StackBlitz 例子
  • @ritaj : 这是我的场景的StackBlitz

标签: angular nested angular-reactive-forms formarray


【解决方案1】:

阿卜杜勒你有两个不同

  1. “提出问题的结构”
  2. 表格

但是您没有定义您的表单。为此,您需要知道要如何发送到服务器的数据。我必须假设你想向服务器发送一些类似的东西

[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'}
]

如您所见,无论如何您只需要一个唯一的formArray,您使用服务器的响应来创建表单的视图,而不是formArray

你想向服务器发送什么?

好吧,如果我们选择第三个选项是 FormArray,而不是 formGroup。别管它。 FormArray 可以像 FormGroup 一样进行管理。首先我们来看看如何创建表单数组

 ngOnInit() {
    this.feedbackForm = new FormArray(this.data.map(x=>new FormGroup({
      'question':new FormControl(x.description),
      'answer':new FormControl('')
    })))
  }

看到 feedbackform 是一个表单数组。如何创建它?对于每个问题,创建一个带有两个表单控件、问题和答案的 formGroup

.html 变得像

<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>

看到了,我们使用“数据”来显示收音机的标签并为收音机赋予价值,但表单只是一个表单数组。如果我们的“数据”对问题和答案都有一个“id”,我们可以使用它

stackblitz

注意:我只是在 stackblitz 中添加了一个带有 FormArray 的典型 FormGroup,因为它与 .html 不同

【讨论】:

  • 如果您查看我的问题中的模板,我需要将选定的答案发送到服务器。但我对我的表单模板感到震惊。读取控件时显示错误。请帮忙
  • 你能举一个你想发送的数据的例子(格式为json)吗?否则你本末倒置
  • 这与您在回答中提到的相同。您回复中的第二个选项。包含问题和选定答案的对象数组
  • @Abdult,我更新了我的答案。但重要的是,在创建 FormGroup(或 FormArray)之后,我们需要知道要发送到服务器的内容。一开始只在 .html {{myform?.value|json}} 中有线,然后我们仔细编写 html 标签,考虑到它是一个 formArray,我们首先使用 formGroup 来引用它,formArray.controls 来控制它。如果我们的控件是一个 FormGroup,则创建一个 div 来表示 Angular 是一个表单组,等等。
  • 感谢您的精彩解释。你真的值得敬礼。
【解决方案2】:

你做的有点“颠倒”。 正确的方法是遍历数组的每个成员并为其创建控件,转到嵌套数组,为它们创建控件,然后将其推送到问题数组。

SetControl 仅替换现有控件。 https://angular.io/api/forms/FormArray#setcontrol.

用这个替换初始定义。

  feedbackForm:FormGroup = this._fb.group({
    questions:this._fb.array([])
  })

并尝试用这个替换最后一个。

if (this.questionsResponse.value.length > 0) {
    this. questionsResponse.forEach(question => {
    (this.feedbackForm.get('questions') as FormArray).push(this.fb.group({
      description:question.description,
      answers:this.fb.array([...question.answers.map(answer => 
         this.fb.group(answer))])
     }))
    })
  }

编辑:这是上面代码显示所需的模板。

<form [formGroup]="feedbackForm" novalidate (ngSubmit)="send()">
    <div formArrayName="questions">
        <div *ngFor="let question of feedbackForm.get('questions').controls; let i=index;">
            <p>{{feedbackForm.get(['questions',i,'description']).value}}</p>
            <div [formGroupName]="i">
        <div formArrayName="answers">
          <div *ngFor="let ans of feedbackForm.get(['questions',i,'answers']).controls; let j = index">
              <div [formArrayName]="j">
                <input formControlName="description" />
              </div>
          </div>
        </div>
            </div>
        </div>
    </div>

    <input type="submit" value="Send">
</form>

<pre> {{feedbackForm.value | json}} </pre>

【讨论】:

  • @Qeilson 感谢您的帮助和回复。我已根据您的回答进行了更改,但我的模板出现错误。这是我的场景的StackBlitz。我还更新了问题以反映我的模板。
  • @Abdul ive 使用所需的模板编辑了 aswer :)
  • 感谢模板
猜你喜欢
  • 1970-01-01
  • 2021-04-06
  • 1970-01-01
  • 2018-07-14
  • 2018-06-22
  • 1970-01-01
  • 2020-07-02
  • 2018-03-07
  • 1970-01-01
相关资源
最近更新 更多