如何使用 set 控件方法填充 FormArray 的值?

How to populate a value for FormArray using set control method?

我正在使用动态输入字段的反应形式。我用 FormArray 生成了这些字段。现在,我试图在编辑屏幕上用数据预填充表单,但无法做到。我尝试使用 setControl 方法进行填充,但出现此错误 Cannot find control with path: 'books -> 0 -> name'

这些是我参考的资料

  1. https://alligator.io/angular/reactive-forms-formarray-dynamic-fields/

组件

import { Component } from '@angular/core';
import { FormBuilder, FormGroup, FormArray } from '@angular/forms';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs';

export interface ServerResponse {
  books: any;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  formGroup: FormGroup;
  books: FormArray;

  constructor(
    private http: HttpClient,
    private formBuilder: FormBuilder,
  ) {

  }

  createForm() {
    this.formGroup = this.formBuilder.group({
      books: this.formBuilder.array([this.createBookForm()]),
    });
  }

  createBookForm() {
    return this.formBuilder.group({
      name: [],
      author: [],
    });
  }

  addBook() {
    this.books = this.formGroup.get('books') as FormArray;
    this.books.push(this.createBookForm());
  }

  getData(): Observable<ServerResponse> {
    return this.http.get<ServerResponse>('https://demo0331989.mockable.io/library/data/book');
  }

  populateData() {
    this.getData().subscribe(data => {
      this.formGroup.setControl('books', this.formBuilder.array(data.books || []));
    });
  }

  ngOnInit() {
    this.createForm();
    this.populateData();
  }
}

HTML

<form [formGroup]="formGroup">
  <div formArrayName="books" *ngFor="let book of formGroup.get('books')['controls']; let i = index;">
    <div class="row" [formGroupName]="i">
      <input type="text" autocomplete="off" placeholder="*Name"
      formControlName="name">
      <input type="text" autocomplete="off" placeholder="*Author"
      formControlName="author">
      <button type="button" class="btn btn-success" (click)="addBook();">Add</button>
    </div>
  </div>
</form>

我也在 Stackblitz. Sample/mock data 中共享要预填充的代码。我不确定我在这里遗漏了什么!

I did a fork from your stackblitz example,一起来看看吧。当您想要预填充表单时,您需要创建 BookForm 并将其传递到 setControl 中,而不仅仅是数组。

填充表单数组时,您需要用填充的表单组填充它,因此它看起来像这样:

populateData() {
  this.getData().subscribe(data => {
    const books = this.formGroup.get('books') as FormArray; // get the array
    books.clear(); // clear the array 
    data.books.forEach(b => { // iterate data
      let fg = this.createBookForm(); // create the group
      fg.reset(b); // fill the data
      books.push(fg); // add to array
    });
    this.addBook(); // add blank form to end if desired
  });
}

清除表格部分/在末尾添加空白可能需要也可能不需要。

这里是一个固定的闪电战:https://stackblitz.com/edit/angular-9ts4yv?file=src/app/app.component.ts

disclamer 这个答案与@bryan60 的答案互补,

我喜欢我的函数 createBookForm 作为参数 "data",所以

createBookForm(data:any) {
    data=data||{name:null,author:null}
    return this.formBuilder.group({
      name: data.name,
      author: data.author,
    });
  }

这允许我们写

createBookForm(null) //create a FormGroup with name and author and values null
//or 
createBookForm({name:"Linus Administration",author:"Roger"}) //the formgroup has values

我们的函数 populateData 变得更加简单

  populateData() {
    this.getData().subscribe(data => {
      const books = this.formGroup.get('books') as FormArray;
      books.clear();
      data.books.forEach(b => {
        books.push(this.createBookForm(b))
      });
    });
  }

注意:我看不出有必要声明一个具有独特属性(即 FormArray)的 formGroup,请参阅我在

中的回答等