Angular2 动态生成响应式表单

Posted

技术标签:

【中文标题】Angular2 动态生成响应式表单【英文标题】:Angular2 dynamically generating Reactive forms 【发布时间】:2018-05-13 10:57:45 【问题描述】:

我有一个概念问题,想要一些建议。 所以我有一个组件 myFormArray,它是一种反应形式。它接受一个输入数组,并相应地创建多个 FormControls。

@Component(
selector: 'myFormArray',
templateUrl: 'formarray.component.html'
)

export class FormArrayComponent 
@Input() classFields: any[];  

userForm = new FormGroup();

ngOnInit()
// psuedocode here, but I know how to implement
    for (# of entries in classFields)
    userForm.FormArray.push(new FormControl());

现在,在我的父 html 中,我将动态生成多个 myFormArray。如果这令人困惑,假设我正在这样做:

     <myFormArray [classFields] = "element.subArray"/>
     <myFormArray [classFields] = "element2.subArray"/>
     <button (click) = "save()"> //I don't know how to implement this!

在页面的最后,我想要一个保存按钮,它可以以某种方式获取用户输入到所有表单中的所有值,并将所有这些数据推送到服务组件中的数组中。我不确定这部分到底该怎么做。请注意,我不希望每个动态生成的表单组件都有单独的提交按钮。

我将如何实现此功能?谢谢!

【问题讨论】:

在 angular.io/guide/dynamic-form 你有一个完整的动态 froms 示例 我已经读过了,但要么我读错了,要么它没有回答我的问题。它只是根据不同的输入更改表单属性,我已经在 myFormArray 中完成了。 Dynamically creating input forms in Angular2的可能重复 这个链接也有很大帮助。这是一种引用组件的多个实例的方法,然后您可以从您的 formControl/array/whatever 中提取信息:***.com/questions/40165294/… 【参考方案1】:

你的开始是好的,但你必须以不同的方式编写你的源代码。

代替这个例子,app.components.ts 是主组件,my-array.component.ts 是子组件。

我们的测试数据

classFields1: any[] = ['firstname', 'lastname', 'email', 'password'];
classFields2: any[] = ['country', 'city', 'street', 'zipcode'];

步骤 1. 使用 FormBuilder 创建表单 (app.component.ts)

您必须像这样从@angular/forms 导入FormBuilderFormGroup

import  FormBuilder, FormGroup  from '@angular/forms';

然后在构造函数中定义:

constructor(private formBuilder: FormBuilder)  

第 2 步。定义新的空 FormGrooup

现在您可以像这样在ngOnInit 中定义新的空FormGroup:

ngOnInit() 
  this.myForm = this.formBuilder.group();

第 3 步:动态创建 FormControls (app.component.ts)

现在您可以通过迭代classFields 来动态创建FormControls。为此,我建议创建自己的功能。这个函数有两个参数:arrayNameclassFields。使用arrayName,我们可以设置FormArray-control 的自定义名称。 classFields-Array 我们将用于迭代。我们为空的FormArray 创建常量变量,我们称之为arrayControls。在此之后,我们遍历classFields 并为每个元素创建FormControl,我们称之为control,并将这个control 推送到arrayControls。在这个函数的最后,我们使用arrayName 将我们的arrayControls 添加到我们的表单中,并使用自定义名称。这是一个例子:

createDynamicArrayControls(arrayName: string, classFields: any[]) 
    const defaultValue = null;
    const arrayControls: FormArray = this.formBuilder.array([]);
    classFields.forEach(classField => 
      const control = this.formBuilder.control(defaultValue, Validators.required);
      arrayControls.push(control);
    )
    this.myForm.addControl(arrayName, arrayControls);
  

@angular/forms 导入FormControlFormArray。你的导入行应该是这样的:

import  FormBuilder, FormGroup, FormArray, FormControl  from '@angular/forms';

现在在ngOnInit中调用createDynamicFormControls-Function。

步骤 4. 此动态表单的 HTML 模板 (app.component.html)

对于这个例子,我创建了以下模板:

<h1>My Form</h1>
<form [formGroup]="myForm">
  <div formGroupName="test1">
    <app-my-array [classFields]="classFields1" [arrayFormName]="myForm.controls.test1"></app-my-array>
  </div>
  <div formGroupName="test2">
    <app-my-array [classFields]="classFields2" [arrayFormName]="myForm.controls.test2"></app-my-array>
  </div>
  <button type="button" (click)="saveForm()">Submit</button>
</form>

这里有formGroupName 的新div 元素。这个组名是我们表单中的arrayName。我们将表单数组通过@Input 传递给my-array.component

第 5 步。MyArrayComponent

现在这个组件非常简单:

import  Component, OnInit, Input  from '@angular/core';
import  FormGroup  from '@angular/forms';

@Component(
  selector: 'app-my-array',
  templateUrl: './my-array.component.html',
  styleUrls: ['./my-array.component.css']
)
export class MyArrayComponent implements OnInit 

  @Input() classFields: any[];
  @Input() arrayFormName: FormGroup;

  constructor()  

  ngOnInit()  


这里我们只有两个@Input 变量。 (我知道,这个变量可以有更好的名字:-))。

步骤 6. MyArrayComponent 的 HTML

<div [formGroup]="arrayFormName">
  <div *ngFor="let class of arrayFormName.controls; let index = index;">
    <label [for]="classFields[index]"> classFields[index] </label>
    <input type="text" [id]="classFields[index]" [formControlName]="index" />
  </div>
</div>
<br>

这是 Stackblitz 上的工作示例:https://stackblitz.com/edit/angular-wawsja

如果您有任何问题,请在 cmets 中向我提问或阅读有关 Reactive Forms here 的 Angular 文档。

【讨论】:

感谢您的详细解答!但我的问题确实是这样的:在我的 parent.html 中,我将创建两个 MyArrayComponent 实例。是否有可能有一个保存按钮,可以同时看到这些实例和其中的值? 编辑问题以反映我的评论 @ellusion 今天晚些时候我会更新我的答案 @ellusion 我已经为你更新了我的例子 qeustion stackblitz.com/edit/angular-wawsja

以上是关于Angular2 动态生成响应式表单的主要内容,如果未能解决你的问题,请参考以下文章

Angular2如何获取动态生成的HTML元素的引用

动态增加响应式表单

动态生成 Eureka Form Rows

动态生成表单

为啥我应该在构造函数而不是 ngOnInit 中创建我的 Angular2 响应式表单?

Javascript未从动态生成的表单提交数据