Angular Dynami c форма с переменным содержанием - PullRequest
0 голосов
/ 09 марта 2020

Мне нужно представить набор вопросов, извлеченных из API, и у меня возникли проблемы с отображением формы в шаблоне и получением правильных значений ответа пользователя. Формат ответа API следующий:

{
  questions: [
  {
    text: 'Is this a question?',
    id: 'question1',
    answers: [
      { text: 'Yes', id: 'answer1' },
      { text: 'No!', id: 'answer2' },
      { text: 'Don't know?', id: 'answer3' }
     ]
   }
  ]
}

Я создал форму, которая выглядит следующим образом:

В компоненте

constructor(private fb: FormBuilder) {
    this.questionsAnswersForm = this.fb.group({
      answers: this.fb.array([])
    }); 
  }
this.initFormWithQAs()
initFormWithQAs(): void {
  this.questions.map(() =>
    (<FormArray>this.questionsAnswersForm.get('answers')).push(
      this.addQuestionFormGroup()
    )
  );
}
 addQuestionFormGroup(): FormGroup {
    return this.fb.group({
      questionId: [null, Validators.required],
      answerId: [null, Validators.required]
    });
  }

В шаблоне

<div formArrayName="answers" *ngFor="let q of questions">
    <h5>{{ q.text }}</h5>
      <form  [formGroupName]="q.id" class="qa-list">
        <label *ngFor="let answer of q.answers">
          <input
            type="radio"
            [value]="answer.id"
            [formControlName]="answer.id"
          />
         <span>{{ answer.text }}</span>
       </label>
     </form>
  </div>

Анкета отображается на экране с правильным текстом, но переключатели не выбраны однозначно (работают как флажки), значения при отправке формы всегда равны нулю, и я также получаю следующую ошибку:

TypeError: Невозможно создать свойство 'validator' для строки 'question1'

Заранее спасибо за помощь!

1 Ответ

1 голос
/ 09 марта 2020

Я только что создал для вас динамическую c реактивную форму, основанную на данных из API

. Это файл .ts

  questions = [
    {
      text: 'Is this a question?',
      id: 'question1',
      answers: [
        { text: 'Yes', id: 'answer1' },
        { text: 'No!', id: 'answer2' },
        { text: 'Dont know?', id: 'answer3' }
      ]
    }
  ]


  questionsAnswersForm: FormGroup;
  constructor(private fb: FormBuilder) {
    this.questionsAnswersForm = this.fb.group({});
    this.initFormWithQAs();
  }

  initFormWithQAs(): void {
    this.questions.forEach((question) => {
      const questionAnswersGroup = this.fb.group({});
      question.answers.forEach(answer => {
        questionAnswersGroup.addControl(answer.id, new FormControl(false));
      });
      this.questionsAnswersForm.addControl(question.id, questionAnswersGroup);
    });
  }

  display() {
    console.log(this.questionsAnswersForm.value);

  }

// Чтобы добавить требуемую пользовательскую проверку

initFormWithQAs(): void {
    this.questions.forEach((question) => {
      const questionAnswersGroup = this.fb.group({});
      questionAnswersGroup
        .setValidators([function (control) {
          if (!Object.values(control.value).reduce((a, b) => a || b)) {
            return { required: true };
          }
          return null
        }]);
      question.answers.forEach(answer => {
        questionAnswersGroup.addControl(answer.id, new FormControl(false));
      });
      this.questionsAnswersForm.addControl(question.id, questionAnswersGroup);
    });
  }

и это html шаблон

<form [formGroup]="questionsAnswersForm">
    <div [formGroupName]="q.id" *ngFor="let q of questions">
        <h5>{{ q.text }}</h5>
        <label *ngFor="let answer of q.answers">
            <input type="radio" [value]="answer.id" [formControlName]="answer.id" />
            <span>{{ answer.text }}</span>
        </label>
    </div>
    <button (click)="display()">Display values</button>
</form>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...