Angular - Zagnieżdżone FormArray

0

Cześć. Próbuję zrobić formularz do tworzenia Quizu w postaci:

Quiz
{
  tytuł quizu
  opis
  pytania{
    treść pytania
    odpowiedzi{
      treść odpowiedzi,
      czy poprawna
    }
  }
}

Znalazłem bardzo łany przykład w google i zmieniłem na swoje potrzeby, jednak nie działa on do końca poprawnie.
Otóż w jednym miejscu wyrzuca błąd "Property 'controls' does not exist on type 'AbstractControl' " przy pętli w której chcę iterowac po pytaniach:

*ngFor="
    let question of quizForm.get('questions').controls;
    let questionIndex = index
  "

Dziwi mnie to, ponieważ w kolejnej pętli w której iteruję po odpowiedziach w pytaniach, która w mojej ocenie jest bardzo podobna, ten błąd już nie występuje:

*ngFor="
    let answer of question.get('answers').controls;
    let answerIndex = index
  "

Proszę o wskazówkę.
Link do kodu: https://stackblitz.com/edit/angular-ivy-wa5vyt?file=src/app/app.component.html

Kod komponentu:

import { Component, OnInit } from '@angular/core';
import { FormArray, FormGroup, FormBuilder, Validators } from '@angular/forms';

@Component({
  selector: 'app-courseMaker',
  templateUrl: './courseMaker.component.html',
  styleUrls: ['./courseMaker.component.css']
})
export class CourseMakerComponent implements OnInit {
     
  constructor(private fb: FormBuilder) {}  

  ngOnInit(): void {}

  //
  // Quiz
  //

  quizForm = this.fb.group({
    quizDetails: this.fb.group({
      quizTitle: ['', Validators.required],
      description: ['', Validators.required],
    }),
    questions: this.fb.array([])
  });
  
  get questions(): FormGroup {
    return this.fb.group({
      question: ['', Validators.required],
      answers: this.fb.array([]),
    });
  }

  get answers(): FormGroup {
    return this.fb.group({
      answer: ['', Validators.required],
      isItCorrect: ['', Validators.required],
    });
  }

  addQuestion() {
    (this.quizForm.get('questions') as FormArray).push(this.questions);
  }

  deleteQuestion(index : number) {
    (this.quizForm.get('questions') as FormArray).removeAt(index);
  }

  addAnswer(question) {
    question.get('answers').push(this.answers);
  }

  deleteAnswer(question, index : number) {
    question.get('answers').removeAt(index);
  }

  savePage() {
    
  }
}

<form [formGroup]="quizForm" (ngSubmit)="savePage()">
                <div class="form-header" formGroupName="quizDetails">
                  <label>Quiz title <input formControlName="quizTitle"/></label>
                  <label>Description <input formControlName="description"/></label>
                </div>
              
                <hr />
                <button type="button" (click)="addQuestion()">addQuestion</button>
                <div formArrayName="questions">
                 <!-- BLAD JEST TUTAJ!-->
                  <div
                    class="questions"
                    *ngFor="
                      let question of quizForm.get('questions').controls;
                      let questionIndex = index
                    "
                    [formGroupName]="questionIndex"
                  >
                    <label
                      >question <input formControlName="question" />
                      <button (click)="deleteQuestion(questionIndex)">x</button></label
                    >
                    <hr />
                    <button type="button" (click)="addAnswer(question)">Add question</button>
                    <div formArrayName="answers">
                      <div
                        class="answers"
                        *ngFor="
                          let answer of question.get('answers').controls;
                          let answerIndex = index
                        "
                        [formGroupName]="answerIndex"
                      >
                        <label
                          >answer <input formControlName="answer" />
                          <button (click)="deleteAnswer(question, answerIndex)">x</button></label
                        >
                        <mat-form-field appearance="fill">
                          <mat-select formControlName="isItCorrect"
                                  placeholder="isItCorrect">
                              <mat-option value="text">Yes</mat-option>
                              <mat-option value="code">No</mat-option>
                          </mat-select>
                      </mat-form-field>
                      </div>
                    </div>
                  </div>
                </div>
              </form>
0

Bo questions: this.fb.array([]) jest typu fb.array, a żebyś miał dostęp do controls musisz mieć this.fb.group(). Z tego co wiem, to FormArray już samo sobie zwraca tablice pól.

Nie korzystałem jeszcze z FormArray ale tutaj sypie ci błędem, bo get.('questions') nie ma controls

quizForm.get('questions').controls

Spróbuj, bez controls

<div
class="questions"
*ngFor="
let question of quizForm.get('questions');
let questionIndex = index
"
[formGroupName]="questionIndex"
>
0

Udało mi się naprawić błąd deklarując quizForm: any. Tylko czy to dobry pomysł i czy jest to jedyne rozwiązanie?

0

Zwróć uwagę, że w addAnswer(), nie rzutujesz na FormArray przed zrobieniem push. JavaScript rządzi się swoimi prawami 🤔

1 użytkowników online, w tym zalogowanych: 0, gości: 1