Angular 2 Форма "Не удается найти управление с помощью пути"

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

Не удается найти элемент управления с помощью пути: 'list_items → list_item'

Мой компонент:

@Component({
  selector: 'app-list',
  templateUrl: './list.component.html',
  styleUrls: ['./list.component.css']
})
export class ListComponent implements OnInit {

  listForm: FormGroup;

  constructor(private nodeService: NodeService, private messageService: MessageService, private fb: FormBuilder,
                private listService: ListService) { 
    this.listForm = this.fb.group({
      title: ['', [Validators.required, Validators.minLength(5)]],
      list_items: this.fb.array([
        this.initListItem(),
        ])
    });
  }


  initListItem() {
    return this.fb.group({
      list_item: ['']
    });
  }
  initListItemType() {
    return this.fb.group({
      list_item_type: ['']
    });
  }

  addListItem() {
    const control = <FormArray>this.listForm.controls['list_items'];
    control.push(this.initListItem());
  }

Шаблон (list.component.html):

<h2>Add List </h2>

<form [formGroup]="listForm" novalidate (ngSubmit)="addList(listForm)">
  <div class="form-group">
    <input type="text" class="form-control" formControlName="title" placeholder="Title">
  </div>

  <div formArrayName="list_items">
    <div *ngFor="let list_item of listForm.controls.list_items.controls; let i=index" class="panel panel-default">
      {{i + 1}}.) <input type="text" formControlName="list_item" placeholder="List Item" class="form-control">
    </div>
    <a (click)="addListItem()">Add List Item +</a>

  </div>

  <button type="submit">Submit</button>
</form>

Название работает очень хорошо, но я не могу найти ошибку, которая у меня есть с "formControlName", которая вызывает ошибку.

Заранее благодарим за помощь в этой проблеме.

Обновить с помощью того, что я изменил list.component.html

<h2>Add List </h2>

<form [formGroup]="listForm" novalidate (ngSubmit)="addList(listForm)">
  <div class="form-group">
    <input type="text" class="form-control" formControlName="title" placeholder="Title">
  </div>

  <div formArrayName="list_items">
    <div *ngFor="let list_item of listForm.controls.list_items.controls; let i=index" class="panel panel-default">
      {{i + 1}}.) <input type="text" formControlName="{{i}}" placeholder="List Item" class="form-control">
    </div>
    <a (click)="addListItem()">Add List Item +</a>

  </div>

  <button type="submit">Submit</button>
</form>

И в моем компоненте я изменил конструктор и мой метод addListItem:

listForm: FormGroup;

  constructor(private nodeService: NodeService, private messageService: MessageService, private fb: FormBuilder,
                private listService: ListService) { 
    this.listForm = this.fb.group({
      title: ['', [Validators.required, Validators.minLength(5)]],
      list_items: this.fb.array([
          [''],
        ])
    });
  }

  addListItem() {
    const control = <FormArray>this.listForm.controls['list_items'];
    control.push(this.fb.control(['']));
    console.log(control)
  }

Ответ 1

Должен быть отображен formControlName в форме html и ваш файл компонента.

<div *ngFor="let list_item of [0,1,2]; let i=index" class="panel panel-default">

  {{i + 1}}.) <input type="text" formControlName='{{i}}' placeholder="List Item" class="form-control">
</div>

============

list_items: this.fb.array([
 [''],  //0 points to this
 [''],  //1 points to this
 ['']   //2 points to this
])

Ответ 2

Обратите внимание, что если ваш FormArray содержит другие элементы управления FormGroup (которые содержат другие экземпляры FormControl), вам необходимо сделать это, чтобы получить доступ к элементам управления внутри каждого FormGroup:

        <div *ngFor="let item of myFormArray.controls; let i=index">
            <div formGroupName="{{i}}">
                <input formControlName="myFormGroupSubControl1" />
                <input formControlName="myFormGroupSubControl2" />

Ответ 3

Я также столкнулся с этой ошибкой, и я решил эту проблему, инициировав переменные класса (элементы в this.fb.array([])).

Фрагмент кода

    mobileNumbers: this.fb.array([this.fb.group(new MobileNumber('IN'))]),

Если используется класс MobileNumber.

export class MobileNumber{
    public country_code: string;
    public mobile_number: string;
    constructor($cc){
        this.country_code = COUNTRY_CODES[$cc];
    }
}

Для

export class MobileNumber{
    public country_code = '';
    public mobile_number = '';
    constructor($cc){
        this.country_code = COUNTRY_CODES[$cc];
    }
}

Ответ 4

Простой пример с FormArray @stackblitz (gist'd ниже)

app.component.ts

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

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: [ './app.component.css' ]
})
export class AppComponent implements OnInit {
  fg: FormGroup;
  constructor(private fb: FormBuilder){}
  ngOnInit() {
  this.fg = this.fb.group({
    address: this.fb.group({
      street: ['', Validators.required],
    }),
    aliases: this.fb.array([])
  });
  const fa = (this.fg.get('aliases')as FormArray);
  this.addNewAlias();
  }
  addNewAlias(){
    const fa = (this.fg.get('aliases')as FormArray);
    fa.push(this.fb.group({
      name: ['', Validators.required]
    }));
  }
  deleteAlias(i:number){
    const fa = (this.fg.get('aliases')as FormArray);
    fa.removeAt(i);
    if(fa.length===0) this.addNewAlias();
  }
}

app.component.html

<form [formGroup]="fg" class="spaced">
  <h3>Nested in Group:</h3>
  <div formGroupName="address" class="spaced">
    <label>
      <input type="text" formControlName="street">
      valid: {{fg.get('address').get('street')?.valid}}
    </label>
  </div>
  <h3>Nested in Array:</h3>
  <div formArrayName="aliases" *ngFor="let alias of fg.get('aliases').controls; let i = index;" class="border">
    <div [formGroupName]="i">
      <label>
        Alias {{i+1}}:
        <input formControlName="name" placeholder="Item name">valid: {{alias.get('name')?.valid}}
      </label>
      <button type="button" (click)="deleteAlias(i)">X</button>
    </div>
  </div>
  <button type="button" (click)="addNewAlias()">add</button>
</form>
<div>form valid: {{fg?.valid}}</div>