angular FormArray用法指南

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了angular FormArray用法指南相关的知识,希望对你有一定的参考价值。

参考技术A

angular表单的三大基本构造块
1.FormControl:单个独立的表单控件;
2.FormGroup:一组FormControl实例;
3.FormArray:控件数组,控件可为FormControl、FormGroup、FormArray的实例;

FormBuilder: 根据用户指定的配置创建 abstractControl, FormBuilder 提供的语法糖可快速实例化 FormControl 、 FormGroup 、 FormArray 。

FormArray 的使用场景:需要循环遍历的表格,实现动态增加或删除表数据
常用方法

html表格中如果有合计需要动态计算,可在合计中使用ngModel绑定需要累加的控件值

场景描述:在一个 form 表单中,需要动态添加或删除某个表单集

从 Angular 中的 FormArray 中删除所有项目

【中文标题】从 Angular 中的 FormArray 中删除所有项目【英文标题】:Remove all items from a FormArray in Angular 【发布时间】:2017-06-10 16:02:21 【问题描述】:

我在 FormBuilder 中有一个表单数组,我正在动态更改表单,即点击从应用程序 1 加载数据等。

我遇到的问题是所有数据都加载了,但 FormArray 中的数据仍然存在,只是将旧项目与新项目连接起来。

如何清除 FormArray 以仅包含新项目。

我试过了

const control2 = <FormArray>this.registerForm.controls['other_Partners'];
control2.setValue([]);

但它不起作用。

有什么想法吗?

ngOnInit(): void 
  this.route.params.subscribe(params => 
    if (params['id']) 
      this.id = Number.parseInt(params['id']);
     else  this.id = null;
  );
  if (this.id != null && this.id != NaN) 
    alert(this.id);
    this.editApplication();
    this.getApplication(this.id);
   else 
    this.newApplication();
  


onSelect(Editedapplication: Application) 
  this.router.navigate(['/apply', Editedapplication.id]);


editApplication() 
  this.registerForm = this.formBuilder.group(
    id: null,
    type_of_proposal: ['', Validators.required],
    title: ['', [Validators.required, Validators.minLength(5)]],
    lead_teaching_fellow: ['', [Validators.required, Validators.minLength(5)]],
    description: ['', [Validators.required, Validators.minLength(5)]],
    status: '',
    userID: JSON.parse(localStorage.getItem('currentUser')).username,
    contactEmail: JSON.parse(localStorage.getItem('currentUser')).email,
    forename: JSON.parse(localStorage.getItem('currentUser')).firstname,
    surname: JSON.parse(localStorage.getItem('currentUser')).surname,
    line_manager_discussion: true,
    document_url: '',
    keywords: ['', [Validators.required, Validators.minLength(5)]],
    financial_Details: this.formBuilder.group(
      id: null,
      buying_expertise_description: ['', [Validators.required, Validators.minLength(2)]],
      buying_expertise_cost: ['', [Validators.required]],
      buying_out_teaching_fellow_cost: ['', [Validators.required]],
      buying_out_teaching_fellow_desc: ['', [Validators.required, Validators.minLength(2)]],
      travel_desc: ['', [Validators.required, Validators.minLength(2)]],
      travel_cost: ['', [Validators.required]],
      conference_details_desc: ['', [Validators.required, Validators.minLength(2)]],
      conference_details_cost: ['', [Validators.required]],
    ),

    partners: this.formBuilder.array([
        //this.initEditPartner(),
        //this.initEditPartner()
        // this.initMultiplePartners(1)
      ]
    ),
    other_Partners: this.formBuilder.array([
      //this.initEditOther_Partners(),
    ])
  );


getApplication(id) 
  this.applicationService.getAppById(id, JSON.parse(localStorage.getItem('currentUser')).username)
    .subscribe(Response => 
      if (Response.json() == false) 
        this.router.navigateByUrl('/');
       else 
        this.application = Response.json();
        for (var i = 0; i < this.application.partners.length;i++) 
          this.addPartner();
        
        for (var i = 0; i < this.application.other_Partners.length; i++) 
          this.addOther_Partner();
        

        this.getDisabledStatus(Response.json().status);
        (<FormGroup>this.registerForm) .setValue(Response.json(),  onlySelf: true );
      
    );

点击时未调用ngOnInit

【问题讨论】:

一个相关问题is tracked here on the Angular repo 【参考方案1】:

我有同样的问题。有两种方法可以解决这个问题。

保留订阅

您可以通过在循环中调用removeAt(i) 函数来手动清除每个FormArray 元素。

clearFormArray = (formArray: FormArray) => 
  while (formArray.length !== 0) 
    formArray.removeAt(0)
  

这种方法的优点是您的formArray 上的任何订阅(例如在formArray.valueChanges 注册的订阅)都不会丢失。

请参阅FormArray documentation 了解更多信息。


更清洁的方法(但会破坏订阅引用)

您可以将整个 FormArray 替换为新的。

clearFormArray = (formArray: FormArray) => 
  formArray = this.formBuilder.array([]);

如果您订阅了 formArray.valueChanges observable,这种方法会导致问题!如果您将 FromArray 替换为新数组,您将丢失对您订阅的 observable 的引用。

【讨论】:

从 Angular 8+ 开始,从 FormArray 中删除所有组件的首选方法是使用 formArray.clear(); 另外,yourFormArray.setValue([]));和 yourFormGroup.setControl('yourFormArray', []); 再见验证这种方法 @Renan 我正在使用 formControl【参考方案2】:

或者您可以简单地清除控件

this.myForm= 
     name: new FormControl(""),
     desc: new FormControl(""),
     arr: new FormArray([])

加点东西array

const arr = <FormArray>this.myForm.controls.arr;
arr.push(new FormControl("X"));

清空数组

const arr = <FormArray>this.myForm.controls.arr;
arr.controls = [];

当您选择并清除多个选项时,有时它不会更新视图。一种解决方法是添加

arr.removeAt(0)

更新

使用表单数组的更优雅的解决方案是在类的顶部使用 getter,然后您可以访问它。

get inFormArray(): FormArray 
    this.myForm.get('inFormArray') as FormArray;

并在模板中使用它

<div *ngFor="let c of inFormArray; let i = index;" [formGroup]="i">
other tags...
</div>

重置:

inFormArray.reset();

推:

inFormArray.push(new FormGroup());

删除索引处的值:1

inFormArray.removeAt(1);

更新 2:

获取部分对象,获取所有错误作为 JSON 和许多其他功能,使用 NaoFormsModule

【讨论】:

“arr.controls = [];”提及真的很棒! @Pian, 只有 const arr = this.myForm.controls.arr; arr.controls = [];正在努力清除表单数组。 TQ inFormArray.at(1).remove(); 给了我一个[ts] Property 'remove' does not exist on type 'AbstractControl'. 编译器错误。 @Pian0_M4n 在你的模板中,let c of inFormArray 应该是let c of inFormArray.controls ?【参考方案3】:

从 Angular 8+ 开始,您可以使用 clear() 删除 FormArray 中的所有控件:

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.length);  // 2

arr.clear();
console.log(arr.length);  // 0

对于以前的版本,推荐的方法是:

while (arr.length) 
   arr.removeAt(0);

https://angular.io/api/forms/FormArray#clear

【讨论】:

这在 Angular 13 中仍然有效【参考方案4】:

Angular 8

只需在 formArrays 上使用 clear() 方法:

(this.invoiceForm.controls['other_Partners'] as FormArray).clear();

【讨论】:

【参考方案5】:

警告!

Angular v6.1.7 FormArray documentation 说:

要更改数组中的控件,请使用 push、insert 或 removeAt FormArray 本身的方法。这些方法可确保控制 在表单的层次结构中正确跟踪。不要修改数组 AbstractControls 用于直接实例化 FormArray,因为 导致奇怪和意外的行为,例如损坏的变化 检测。

如果您直接在 controls 数组上使用 splice 函数作为建议的答案之一,请记住这一点。

使用removeAt 函数。

  while (formArray.length !== 0) 
    formArray.removeAt(0)
  

【讨论】:

【参考方案6】:

Angular v4.4 如果您需要保存对 FormArray 实例的相同引用,请尝试以下操作:

purgeForm(form: FormArray) 
  while (0 !== form.length) 
    form.removeAt(0);
  

【讨论】:

在从数组中弹出元素的同时保留订阅的好方法。 @mtpultz 请注意已接受答案的更改日志 (***.com/posts/41856927/revisions)。当我离开这个答案时,接受的答案与当前不同。【参考方案7】:

您可以轻松地为您的数组定义一个 getter 并将其清除,如下所示:

  formGroup: FormGroup    
  constructor(private fb: FormBuilder)  

  ngOnInit() 
    this.formGroup = this.fb.group(
      sliders: this.fb.array([])
    )
  
  get sliderForms() 
    return this.formGroup.get('sliders') as FormArray
  

  clearAll() 
    this.formGroup.reset()
    this.sliderForms.clear()
  

【讨论】:

【参考方案8】:

更新:Angular 8 终于有了清除数组的方法 FormArray.clear()

【讨论】:

【参考方案9】:

使用 FormArray.clear() 删除 FormArray 中数组的所有元素

【讨论】:

【参考方案10】:

简单

formArray.clear()

足够了

【讨论】:

这应该是现在公认的答案。【参考方案11】:

从 Angular 8 开始,您可以使用 this.formArray.clear() 清除表单数组中的所有值。 这是一种更简单、更有效的替代方法,可以逐个删除所有元素

【讨论】:

【参考方案12】:

提供了数据结构,用于将数组中的信息替换为匹配的内容,您可以使用patchValue

https://angular.io/docs/ts/latest/api/forms/index/FormArray-class.html#!#reset-anchor

patchValue(value: any[], onlySelf, emitEvent?: onlySelf?: boolean, emitEvent?: boolean) : void 修补 FormArray 的值。它 接受与控件结构匹配的数组,并将 尽最大努力将值与组中的正确控件相匹配。

它接受数组的超集和子集而不抛出 一个错误。

const arr = new FormArray([
   new FormControl(),
   new FormControl()
]);
console.log(arr.value);   // [null, null]
arr.patchValue(['Nancy']);
console.log(arr.value);   // ['Nancy', null]

您也可以使用reset

reset(value?: any, onlySelf, emitEvent?: onlySelf?: boolean, emitEvent?: boolean) : void 重置 FormArray。这意味着通过 默认:

数组和所有后代都被标记为原始数组和所有 后代被标记为未触及所有后代的值将是 null 或 null 映射您还可以通过以下方式重置为特定的表单状态 传入与结构相匹配的状态数组 控制。状态可以是独立值或表单状态对象 同时具有值​​和禁用状态。

this.arr.reset(['name', 'last name']);
console.log(this.arr.value);  // ['name', 'last name']

this.arr.reset([   value: 'name', disabled: true,   'last' ]);
console.log(this.arr.value);  // ['name', 'last name']
console.log(this.arr.get(0).status);  // 'DISABLED'

【讨论】:

这肯定意味着数组中的项目数必须完全相同?【参考方案13】:

我从未尝试过使用 formArray,我一直使用 FormGroup,您可以使用以下方法删除所有控件:

Object.keys(this.formGroup.controls).forEach(key => 
          this.formGroup.removeControl(key);
        );

作为 formGroup 的一个实例。

【讨论】:

【参考方案14】:

为了保持代码简洁,我为使用 Angular 7 及以下版本的任何人创建了以下扩展方法。这也可以用于扩展响应式表单的任何其他功能。

import  FormArray  from '@angular/forms';

declare module '@angular/forms/src/model' 
  interface FormArray 
    clearArray: () => FormArray;
  


FormArray.prototype.clearArray = function () 
  const _self = this as FormArray;
  _self.controls = [];
  _self.setValue([]);
  _self.updateValueAndValidity();
  return _self;


【讨论】:

【参考方案15】:

我很晚了,但我找到了其他不需要循环的方法。您可以通过将数组控件设置为空来重置数组。

以下代码将重置您的数组。

this.form.setControl('name', this.fb.array([]))

【讨论】:

【参考方案16】:

如果数组有 100 个项目,则循环将需要很长时间才能删除所有项目。您可以清空 FormArray 的控件和值属性,如下所示。

clearFormArray = (formArray: FormArray) => formArray.controls = []; formArray.setValue([]);

【讨论】:

【参考方案17】:

如果您使用的是 Angular 7 或以前的版本,并且您无权访问 clear() 方法,则有一种方法可以在不执行任何循环的情况下实现:

yourFormGroup.controls.youFormArrayName = new FormArray([]);

【讨论】:

以上是关于angular FormArray用法指南的主要内容,如果未能解决你的问题,请参考以下文章

SASS用法指南

Android 基于Jetpack的MVVM架构入门指南

Android 基于Jetpack的MVVM架构入门指南

SASS用法指南

Android 基于Jetpack的MVVM架构入门指南

任务调度框架 Quartz 用法指南(超详细)