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 =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用法指南的主要内容,如果未能解决你的问题,请参考以下文章