首页 > 解决方案 > 使用 Angular formArray 动态添加表单字段

问题描述

我有几个表单字段,想要动态添加更多来自另一个视图的字段(用户可以在其中输入表单字段类型、长度和名称),我需要使用这些值构造表单字段。

我如何设法构建一个字段(textbox name is 'one'),但是如果我尝试添加另一个字段(textbox name is 'two'),则会出现以下错误,

ERROR Error: Cannot find control with path: 'newfields -> 0 -> two' 

问题组件.html

  <form [formGroup]="issuerTestCaseFrm">
                <div>
                    <label for="inputName3">Issuer Reference Number: </label>
                    <input name="lcid" formControlName="IssuerReferenceNumber" required type="tel" class="form-control">
                </div>
                    <div formArrayName="newfields">
                    <div [formGroupName]="i" *ngFor="let tech of issuerTestCaseFrm.controls.newfields.controls; let i = index">
                    <div *ngFor="let prop of fieldProps">
                                <label class="col-sm-2 control-label">{{fields[prop].label}}</label>
                                <div [ngSwitch]="fields[prop].type">
                                    <input *ngSwitchCase="'text'" [formControlName]="prop"> 
                                </div>
                        </div>
                    </div>
                </div>  
    </form>
<button type="submit" (click)="addNewInputField()"> &nbsp;Add New Column &nbsp; </button>

问题组件.ts

import { Component, ViewEncapsulation, Pipe, PipeTransform, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, Validators, FormControl, FormArray } from '@angular/forms';
import { ModalComponent } from '../../modal/modal.component';
import { NgbModal } from '@ng-bootstrap/ng-bootstrap';
@Component({
  selector: 'viewhistory',
  templateUrl: './issuecomponent.html',
})


export class IssuerTestcaseExecution implements OnInit {
  issuerTestCaseFrm: FormGroup;
  fields: any;
  fieldProps: any;
  formControls = {};
  constructor( 
    private fb: FormBuilder,  
    public modalService: NgbModal,
    ) {
    this.issuerTestCaseFrm = fb.group({
      'IssuerReferenceNumber': ['', Validators.required],
      'newfields': fb.array([]),
    });
  }

  initNewFields(): FormGroup {
    this.fieldProps.forEach(prop => {
      this.formControls[prop] = [this.fields[prop].value, Validators.required];
    });
    return this.fb.group(this.formControls);
  }

 //Assuming these results coming from modal view after add button click
  addNewInputField(): void {
      const modalRef = this.modalService.open(ModalComponent);
      modalRef.result.then((result) => {
         this.fields = {
          [result.fieldname]: {
            type: result.fieldtype,
            value: result.fieldvalue,
            label: result.fieldname,
          },
        };
        this.fieldProps = Object.keys(this.fields);
         const control = <FormArray>this.issuerTestCaseFrm.controls.newfields;
         control.push(this.initNewFields());
      }, (reason) => {

      });
  }
}

我在 stackblitz.com 中添加了示例代码。任何人都可以帮助解决这个问题: https ://stackblitz.com/edit/angular-871vxk?file=src/app/app.component.ts

标签: angular

解决方案


尽管这不能完全帮助您,但需要对表单和组件进行一些更改才能消除此错误

  1. 将表单字段更改为 new FormArray()

     this.issuerTestCaseFrm = fb.group({
       'IssuerReferenceNumber': ['', Validators.required],
       'technologies': new FormArray([]),
    });
    
  2. technologies在组件文件中 创建表单的 getter 。

    get technologies(): FormArray { return this.issuerTestCaseFrm.get('technologies') as FormArray; }
    
  3. 在 HTML 中使用这种方式,添加 formArrayname 并*ngFor在输入字段中添加 [formControlName]="i" 。

    <div [formGroupName]="i" *ngFor="let tech of technologies.controls; let i = index" formArrayName="technologies">
    
    <input class="form-control" *ngSwitchCase="'text'" [formControlName]="i">
    
  4. 当您单击添加按钮时使用control.push(new FormControl())

现在在这里你必须工作如何添加完整的表单域

这是更新的演示

Angular FormArray 参考


推荐阅读