Как отобразить ответ сервера на угловые Реактивные формы с вложенным массивом форм - PullRequest
0 голосов
/ 07 марта 2019

Я разрабатываю форму обратной связи в Angular с использованием подхода реактивных форм.Ответ от сервера имеет массив вопросов, который, в свою очередь, имеет массив ответов.

Вот ответ.

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

Я пытаюсь отобразить вопрос с ответами, и мне нужно, чтобы пользователь выбрал ответ на вопрос, и при отправке мне нужны выбранные значения ответа.

Ответы [ 2 ]

1 голос
/ 07 марта 2019

Абдул, у тебя есть две различия вещи:

  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 может быть mannage как FormGroup. Сначала мы посмотрим, как создать форму Array

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

Обратите внимание, что форма обратной связи является массивом форм. Как создать это? Для каждого вопроса создайте группу Form с двумя элементами управления «Форма»: вопрос и ответ

.html становится похожим на

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

Смотрите, мы используем "данные", чтобы показать метку радиостанций и дать значение радиостанциям, но Форма - это только массив форм. Если у наших «данных» есть «идентификатор» для вопроса и ответа, мы могли бы использовать его

См. stackblitz

ПРИМЕЧАНИЕ. Я просто добавляю в стек стека типичную группу FormGroup с FormArray, потому что он отличается от HTML. 1034 *.

1 голос
/ 07 марта 2019

Вы делали небольшой переворот. Правильный путь состоит в том, чтобы пройти через каждый элемент массива и создать для него элемент управления, перейти к вложенным массивам, создать для них элементы управления aswel, а затем отправить его в массив вопросов.

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

РЕДАКТИРОВАТЬ: Здесь необходим шаблон для отображения кода выше.

<code><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}} 
...