Angular 反应式数组

Angular Reactive Forms Array

我在访问位于 opticanOrders 内的产品数组时遇到问题,该数组位于 orderForm 内。在控制台中,我看到为了访问产品数组,我应该这样引用它:

orderForm.controls.opticianOrders.controls.products.controls

但是没有用。

这是我的组件:

  constructor(private customerService: CustomerService, private fb: FormBuilder) { }

  orderForm: FormGroup;

  ngOnInit() {
    this.orderForm = this.fb.group({
      name: [''],
      surName: [''],
      opticianOrders: this.fb.group({
        orderDescription: [''],
        products: this.fb.array([
          this.initProduct()
        ])
      }),
    });
  }

  save(model: Customer) {
    // call API to save customer
    console.log(model);
  }

  onCancel(form: NgForm){
    this.createState.emit(false);
  }

  initProduct(){
    return this.fb.group({
      name: [''],
      manufacturerName: ['']
    })
  }

  addProduct(){
    const control = <FormArray>this.orderForm.controls['products'];
    control.push(this.initProduct());
  }

  removeProduct(i: number){
    const control = <FormArray>this.orderForm.controls['products']
  }

Html

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

  <!-- name -->
  <div class="form-group">
      <label>Name</label>
      <input type="text" formControlName="name">
  </div>

  <!-- surName -->
  <div class="form-group">
      <label>Last Name</label>
      <input type="text" formControlName="surName">
  </div>

  <div formGroupName="opticianOrders" class="form-group">
      <label>Order Description</label>
      <input type="text" formControlName="orderDescription">
  </div>
  <div formArrayName="products">
          <div *ngFor="let product of orderForm.controls.opticianOrders.controls.products.controls; let i=index">
              <div>
                  <span>Address {{i + 1}}</span>
                  <span *ngIf="orderForm.controls.opticianOrders.controls.products.controls.length > 1" 
                      (click)="removeProduct(i)">
                  </span>
               </div>

               <div [formGroupName]="i">
                  <div>
                      <label>Product name</label>
                      <input type="text" formControlName="name">
                  </div>
              </div>
          </div>
        </div>
    <button type="submit" [disabled]="!orderForm.valid">Submit</button>
</form>

试试这个

orderForm.controls.opticianOrders.controls

请按照以下内容替换您的 HTML 代码

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

  <!-- name -->
  <div class="form-group">
    <label>Name</label>
    <input type="text" formControlName="name">
  </div>

  <!-- surName -->
  <div class="form-group">
    <label>Last Name</label>
    <input type="text" formControlName="surName">
  </div>

  <div class="form-group">
    <label>Order Description</label>
    <input type="text" formControlName="orderDescription">
  </div>
  <div formArrayName="products">
    <div *ngFor="let product of orderForm.controls.products['controls']; let i=index">
      <div>
        <span><strong>Product {{i + 1}}</strong></span>
        <span class="fa fa-times" *ngIf="orderForm.controls['products'].controls.length > 1" (click)="removeProduct(i)">
        </span>
      </div>

      <div [formGroupName]="i">
        <div>
          <label>Product name</label>
          <input type="text" formControlName="name">
        </div>
        <div>
          <label>Product Manufacturer name</label>
          <input type="text" formControlName="manufacturerName">
        </div>
      </div>
    </div>

    <div class="margin-20">
      <a (click)="addProduct()" style="cursor: pointer; text-transform: uppercase; font-weight: 500">
        Add another Entry +
      </a>
    </div>
  </div>
  <button class="btn btn-primary" type="submit" [disabled]="orderForm.invalid">Submit</button>
</form>

请按以下替换TS代码。我在保存表格的方法中使用了一个技巧,看看它是否适合你?

  constructor(private fb: FormBuilder) { }

  orderForm: FormGroup;

  ngOnInit() {
    this.orderForm = this.fb.group({
      name: ['', Validators.required],
      surName: ['', Validators.required],
      orderDescription: ['', Validators.required],
      products: this.fb.array([
        this.initProduct()
      ])
    });
  }

  save() {
    console.log(this.orderForm.value);
    const obj = {
      name: this.orderForm.value.name,
      surName: this.orderForm.value.surName,
      orderDescription: this.orderForm.value.orderDescription,
      opticianOrders: {
        products: this.orderForm.value.products
      },
    };

    console.log(obj);
  }

  initProduct() {
    return this.fb.group({
      name: ['', Validators.required],
      manufacturerName: ['', Validators.required]
    })
  }

  addProduct() {
    const control = <FormArray>this.orderForm.controls['products'];
    control.push(this.initProduct());
  }

  removeProduct(i: number) {
    const control = <FormArray>this.orderForm.controls['products'];
    control.removeAt(i);
  }

您的 stackblitz 代码无效。您没有导入 ReactiveFormsModule 并在 hello.component.ts 中实现了表单代码,您还将模板代码放在 app.component.html.

看我的working sample on stackblitz。它允许您从 FormArray.

添加(单击添加)和删除(单击 'x')产品

两个产品的表单值:

{
  name: 'John',
  surName: 'Doe',
  opticianOrders: {
    orderDescription: '1234',
    products: [
      { name: 'Cookies', manufacturerName: '' },
      { name: 'More Cookies', manufacturerName: '' }
    ]
  }
}

对于 typescript this.orderForm.controls.opticianOrders 是一个 AbstractControl,它没有 controls 属性。您必须先将其转换为 FormGroup。与 products 相同,您必须将其转换为 FormArray.

removeProduct(i: number){
  const aFormGroup = this.orderForm.controls.opticianOrders as FormGroup;
  const aFormArray = aFormGroup.controls.products as FormArray;
  aFormArray.removeAt(i);    
}