简体   繁体   中英

Traversing a nested FormArray in Angular 2

I am trying to traverse through a nested FormArray to keep track of a set of questions, each given their own 'FormControl'. I have created a FormArray called 'groups' as such. The hierarchy goes Groups[Questions[Answers]]

constructor(private surveyService: SurveyService, @Inject(FormBuilder) private fb: FormBuilder) {
    this.survey = <Survey>SURVEYS[0];

    this.reactiveForm = fb.group({
      name: ['', Validators.required],
      groups: fb.array(this.getGroups())
    });

}

getGroups() : AbstractControl[] {
    return Array.apply(null,
      Array(this.survey.groups.length)).map((x, index) => new FormArray(this.getQuestions(index)))
  }

getQuestions(index) : AbstractControl[] {
    return Array.apply(null,
      Array(this.survey.groups[index].questions.length)).map(x => new FormControl(x, Validators.required));
  }

Here is my HTML code:

<form [formGroup]="reactiveForm">
  <div formArrayName="groups">
    <div *ngFor="let group of survey.groups; index as groupIndex" [formArrayName]=groupIndex>
      <h1>{{group.groupName}}</h1>
      <div *ngFor="let question of group.questions; index as questionIndex" [formArrayName]=questionIndex>
        <h2>{{question.question}}</h2>
        <label *ngFor="let answer of question.responses ; index as answerIndex">
          <input type="radio" [value]=answerIndex [formControlName]=questionIndex>{{answer}}
        </label>
      </div>
    </div>
  </div>
</form>

I figure it to work as such: the first ngFor pulls the array of Questions, the second ngFor pulls the array of answers, and then the final ngFor uses [formControlName] in order to bind each question to the same Control, giving it a unique answer. However, the error I get is this:

Error: Cannot find control with path: 'groups -> 0 -> 0 -> 0'

If Groups[0] is an array and Groups[0][0] is also an array, why does the [0] of that suddenly not exist anymore? How should one go about traversing a FormArray like this?

Here is what you have created:

在此处输入图片说明

Now look at your template:

<form [formGroup]="reactiveForm">
  <div formArrayName="groups">
    <div ... [formArrayName]=groupIndex>
      ...
      <div ... [formArrayName]=questionIndex>
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
             Do you see such FormArray in your FormGroup? I don't
        <...
        <label *ngFor="let answer of question.responses ; index as answerIndex">
          <input ...[formControlName]=questionIndex>...
        </label>
      </div>
    </div>
  </div>
</form>

As you can see you Angular can't find FormControl by path groups -> 0 -> 0 -> 0 because it should be groups -> 0 -> 0

So if you will remove redundant [formArrayName]=questionIndex directive then it should work.

Ng-run Example

Tip: use <pre>{{reactiveForm.value | json}}</pre> <pre>{{reactiveForm.value | json}}</pre> to test FormGroup structure

For demo I used simple structure:

export class Group {
  title: string;
  questions: Question[] = [];

}

export class Question {
  title: string;
  answers: Answer[] = [];    
}

export class Answer {
  id: number;
  title: string;
}

StackBlitz Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM