formsarray 中的 formarray.controls 在角度 5 中是什么意思? [英] what does formarray.controls in formsarray mean in angular 5?

查看:32
本文介绍了formsarray 中的 formarray.controls 在角度 5 中是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 angular 5 的新手,所以基本上我还在掌握这些概念.以 Angular 关于反应式表单的文档为例(https://angular.io/guide/reactive-forms),代码如下:

<div *ngFor="let address of secretLairs.controls; let i=index"[formGroupName]="i" ><!-- 重复地址模板-->

secretlairs.controls 是什么意思?它是什么?根据角度,这意味着:

重复项的来源是 FormArray.controls,而不是 FormArray 本身.每个控件都是一个地址 FormGroup,正是之前(现在重复的)模板 HTML 所期望的.

secretlairs.controls 是否包含任何数据?我可以用任何类型的数据替换这个部分,并用从 webapi 获得的数据实例化一个对象本身吗?例如,代替

*ngFor="let address of secretLairs.controls

我用

*ngFor="让地址的地址

其中地址类型为 any 并且数据是从数据库中获取的.

解决方案

首先,表单分为三种类型 - FormControlFormGroupFormArray - 都继承自 AbstractControl.

当您使用响应式表单进行验证并在组件模板中包含 formGroupNameformControlNameformArrayName 时,您实际上是在声明性地定义表单控件树和根 FormGroup 模型之间的映射.

例如,给定以下模板:

<div formGroupName="personalInfo">名字:<input type="text" formControlName="firstName"><br/>姓氏:<input type="text" formControlName="lastName"><br/>

<div formArrayName="城市">热门城市:<input *ngFor="let city of citys; index as i" type="text" [formControlName]="i">

您正在声明性地设置用于收集信息的表单映射,最终将生成特定格式的 JSON 对象.例如,给定上面的表单模型,formGroup.value 将返回:

<代码>{个人信息": {名字:'约翰',姓氏:‘史密斯’},城市":[纽约","温尼伯",多伦多"]}

在模板中声明表单组的结构后,您需要强制创建相应的formGroupformControlformArray 在您的组件类中.在设置每个表单时,您有机会设置其他参数:

 1. 初始表单值2. 同步验证器数组3. 异步验证器数组

这适用于任何抽象控件.

这就是给定上述模板的相应 formGroup 模型的样子:

导出类 AppComponent {名字:字符串,姓氏:字符串;城市:字符串[];@Input() 表单组:表单组;构造函数(私人FB:FormBuilder){//设置初始值this.cities = ['纽约', '温尼伯', '多伦多'];this.firstName = '约翰';this.lastName = '史密斯';//创建一个与模板对应的formGroupthis.formGroup = fb.group({firstName: [this.firstName, Validators.required],lastName: [this.lastName, Validators.required],城市:fb.array(this.cities.map(t=> fb.control(t, Validators.required)))})}}

要绑定到任何表单的验证标志,您可以使用根 formGroup 和路径字符串(支持点)来查找特定的组、控件或数组.

例如:

名字是必填项

希望这能说明问题.

更好的是,鉴于 Reactive Forms 就是在模板中以声明方式设置模型,并在组件类中强制映射相同的模型,您应该考虑定义一个 JSON 模型并改用它.

例如,假设我们有一个自定义模型 MyModel,它有一个 firstName 属性、lastName 属性和一个 cities 属性.组件类看起来像这样:

 导出类 AppComponent {@Input() 模型:MyModel;@Output() modelChange: EventEmitter;@Input() 表单组:表单组;构造函数(私人FB:FormBuilder){this.model = new EventEmitter();//创建一个与模板对应的formGroupthis.formGroup = fb.group({firstName: [this.model.firstName, Validators.required],lastName: [this.model.lastName, Validators.required],城市:fb.array(this.model.cities.map(t=> fb.control(t, Validators.required)))});}提交(){如果(this.formGroup.valid){this.model = this.formGroup.value;this.modelChange.next(this.model);}}}

I am new to angular 5 so basically am still grasping with the concepts. Using Angular's documentation on reactive forms as an example (https://angular.io/guide/reactive-forms), the following code is as given:

<div formArrayName="secretLairs" class="well well-lg">
<div *ngFor="let address of secretLairs.controls; let i=index" 
 [formGroupName]="i" >
    <!-- The repeated address template -->
  </div>
  </div>

What does secretlairs.controls mean and what is it? According to angular it means that:

The source of the repeated items is the FormArray.controls, not the FormArray itself. Each control is an address FormGroup, exactly what the previous (now repeated) template HTML expected.

Does secretlairs.controls contain any data? Can i replace this portion with lets say an object itself with data of type any and instantiated with data obtained from webapi? For example, instead of

*ngFor="let address of secretLairs.controls

i use

*ngFor="let address of addresses

where addresses is of type any and data obtained from database.

解决方案

First, there are three type of forms - FormControl, FormGroup, and FormArray - all inherit from AbstractControl.

When you use Reactive Forms for validation and include either formGroupName, formControlName, or formArrayName in the component's template, you are actually declaratively defining a map between the form control tree and the root FormGroup model.

For example, given the following template:

<div [formGroup]="formGroup">
    <div formGroupName="personalInfo">
         First Name: <input type="text" formControlName="firstName"><br />
         Last Name: <input type="text" formControlName="lastName"><br />
    </div>
    <div formArrayName="cities">
        Top cities: <input *ngFor="let city of cities; index as i" type="text" [formControlName]="i">
    </div>
</div>

You are declaratively setting up a form map for collecting information, which will eventually produce a JSON object in a specific format. For example, given the above form model, formGroup.value would return:

{
   "personalInfo": {
        "firstName: 'John',
        "lastName: 'Smith'
    },
    "cities": [
        "New York",
        "Winnipeg",
        "Toronto"
    ]
 }

Once you've declared the structure of your form group in your template, you need to imperatively create the corresponding formGroup, formControl, and formArray in your component class. As you setup each form, you have the opportunity to set up additional parameters:

  1. Initial Form Value
  2. Array of synchronous validators
  3. Array of asynchronous validators

This applies to any of the abstract controls.

This is what the corresponding formGroup model would look like given the above template:

export class AppComponent {
  firstName: string,
  lastName: string;
  cities: string[];
  @Input() formGroup: FormGroup;
  constructor(private fb: FormBuilder) {
    // setup initial values
    this.cities = ['New York', 'Winnipeg', 'Toronto'];
    this.firstName = 'John';
    this.lastName  = 'Smith';

    // create a formGroup that corresponds to the template
    this.formGroup = fb.group({
      firstName: [this.firstName, Validators.required],
      lastName: [this.lastName, Validators.required],
      cities: fb.array(this.cities.map(t=> fb.control(t, Validators.required)))
    })
  }
}

To bind to any of the form's validation flags, you can use the root formGroup and a path string (which supports dots) to find the particular group, control, or array.

For example:

<div *ngIf="formGroup.get('firstName').errors.required">First Name is Required</div>

Hopefully, that makes it clear.

[Edit]

Better yet, given that Reactive Forms is all about declaratively setting up a model in the template, and mapping the same model imperatively in the component class, you should consider defining a JSON model and using that instead.

For example, suppose we have a custom model MyModel which has a firstName property, lastName property, and a cities property. The component class would look like this:

 export class AppComponent {
  @Input() model: MyModel;
  @Output() modelChange: EventEmitter<MyModel>;

  @Input() formGroup: FormGroup;
  constructor(private fb: FormBuilder) {
    this.model = new EventEmitter<MyModel>();
    // create a formGroup that corresponds to the template
    this.formGroup = fb.group({
      firstName: [this.model.firstName, Validators.required],
      lastName: [this.model.lastName, Validators.required],
      cities: fb.array(this.model.cities.map(t=> fb.control(t, Validators.required)))
    });
  }

  onSubmit() {
     if (this.formGroup.valid) {
        this.model = this.formGroup.value;
        this.modelChange.next(this.model);
     }
  }
}

这篇关于formsarray 中的 formarray.controls 在角度 5 中是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆