Angular 2:无法在反应表单中添加表单组以形成数组

rva*_*iev 9 javascript angular

我正在构建动态表单,并且想要"动态"添加表单组.

这是我的代码几乎可以工作:

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

export class CombinedComponent implements OnInit {

    ltsForm: FormGroup;

    constructor(private formBuilder: FormBuilder) {
    }

    ngOnInit() {
        this.ltsForm = this.initFormGroup();

        // init products
        for (let i = 0; i < 3; i++) { // add dynamically products
            this.addProduct();
        }

        console.log(this.ltsForm); // Array 'prods' is empty
    }

    // initialize form group, but don't add products yet because they will be added dynamically later
    initFormGroup() {
        let group = this.formBuilder.group({
            products: this.initProductGroup()
        });

        return group;
    }

    initProductGroup() {
        let group = this.formBuilder.group(
            {
                //initialize empty formbuilder array
                prods: this.formBuilder.array([])
            }
        );

        return group;
    }

    initProducts() {
        return this.formBuilder.group({
            id: [''],
            value: false, // checkbox value
        });
    }

    addProduct() {
        <FormArray>this.ltsForm.controls['products'].value.prods.push(this.initProducts());

        console.log(this.ltsForm); // Array 'prods' contains 3 FormGroup elements
    }
} 
Run Code Online (Sandbox Code Playgroud)

模板:

<form [formGroup]="ltsForm"
      novalidate
      (ngSubmit)="save(ltsForm)">

    <div formGroupName="products">
        <div formArrayName="prods">

            <div *ngFor="let product of ltsForm.controls.products.value.prods.controls; let i = index">
                <div [formGroupName]="i">
                    <input type="checkbox"
                           formControlName="value"
                           id="product_{{ i }}"
                           name="product_{{ i }}">
                </div>
            </div>

        </div>
    </div>

    <button type="submit"
            [disabled]="!ltsForm.valid">
        Submit
    </button>
</form>
Run Code Online (Sandbox Code Playgroud)

在方法addProduct()中,我将整个FormGroup元素推送到'prods'数组.所以最后ngOnInit()中控制台的输出只包含一个空的'prods'数组,而addProduct()方法中控制台输出的数组包含3个元素.它看起来像this.ltsForm失去了它的引用,并没有更新.有任何想法吗?

UPD:刚刚发现,如果我从模板中删除整个内容,我就会得到充满数据的"prods".

ste*_*nja 23

有一些小的错误和复杂性,所以我减少了你的例子并重新建立了它.Angular团队有一个嵌套表单数组嵌套表单组的例子非常有帮助.这是进程(和plnkr):

  1. 有一个简单的小组工作:{ projects: '' }.
  2. 有一组控件工作的组:{ projects: ['a', 'b', 'c'] }.我跳过了prods,似乎没必要.

    <form [formGroup]="ltsForm" novalidate (ngSubmit)="save()">
      <div formArrayName="products">
        <div *ngFor="let p of products.controls; let i=index">
          <input [formControlName]="i">
        </div>
      </div>
      <button type="submit" [disabled]="!ltsForm.valid">
        Submit
      </button>
    </form>
    
    ...
    
    export class CombinedComponent implements OnInit {
    
      ltsForm: FormGroup;
    
      get products() { return this.ltsForm.get('products'); }
    
      constructor(private formBuilder: FormBuilder) {}
    
      ngOnInit() {
          this.ltsForm = this.formBuilder.group({
            products: this.formBuilder.array([])
          });
    
          for (let i = 0; i < 3; ++i) {
            this.addProduct();
          }
      }
    
      addProduct() {
        this.products.push(this.formBuilder.control(''));
      }
    
      save() {
        console.log(this.ltsForm.value);
      }
    } 
    
    Run Code Online (Sandbox Code Playgroud)
  3. 最后一步用组替换数组中的控件:

    @Component({
      selector: 'combined-component',
      template: `
        <form [formGroup]="ltsForm" novalidate (ngSubmit)="save()">
          <div formArrayName="products">
            <div *ngFor="let p of products.controls; let i=index">
              <div [formGroupName]="i">
                <input formControlName="id">
                <input type="checkbox" formControlName="value">
              </div>
            </div>
          </div>
          <button type="submit" [disabled]="!ltsForm.valid">
              Submit
          </button>
        </form>
      `
    })
    export class CombinedComponent implements OnInit {
    
      ltsForm: FormGroup;
    
      get products() { return this.ltsForm.get('products'); }
    
      constructor(private formBuilder: FormBuilder) {}
    
      ngOnInit() {
          this.ltsForm = this.formBuilder.group({
            products: this.formBuilder.array([])
          });
    
          for (let i = 0; i < 3; ++i) {
            this.addProduct();
          }
      }
    
      addProduct() {
        this.products.push(this.formBuilder.group({
          id: '',
          value: false
        }));
      }
    
      save() {
        console.log(this.ltsForm.value);
      }
    } 
    
    Run Code Online (Sandbox Code Playgroud)