Angular 的 FormArray 什么时候是传统数组,什么时候是 FormArray 对象?
When is Angular's FormArray a traditional array and when is it a FormArray object?
我用 ControlValueAccessor 构建了一个自定义输入组件,它非常适合添加标签作为选择。 (Stackblitz)
我的问题是:
- 当我在表单中实现组件时(城市和州控件)
- 通过选择一些选项为两个控件添加值
- 提交表格
- 有时控件值是选定标签的数组(如预期的那样)
- 其他时候它是一个实际的 FormArray 对象
这是提交 angular 表单后同一组件的两个值的屏幕截图。一个是对象数组(预期),另一个是实际的 FormArray 对象,其中 .value 属性 包含对象数组!
如果您不想访问 StackBlitz,这里有一些它如何工作的代码。
自定义控件是这样实现的。
this.form = this.fb.group({
tags: this.fb.array([])
});
当用户选择下拉项或点击回车时,对象保存如下:
get tagsArray(): FormArray { return this.form.get('tags') as FormArray; }
...
this.tagsArray.push(new FormControl(value));
this.onChange(this.tagsArray); // update controller value
您可以像这样(也在我的 StackBlitz 中)通过在我的 StackBlitz 中的 formGroup 中实现该组件来复制它:
表单初始化
public form: FormGroup = this.fb.group({
states: [],
cities: []
});
模板
<input-tags formControlName="cities" label="Cities" [typeAhead]="cities" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
<input-tags formControlName="states" label="States" [typeAhead]="states" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
但问题是:
什么时候Angular的FormArray是传统数组,什么时候是FormArray Array like object?
当您使用 new FormArray([])
或 formBuilder.array([])
. 创建控件实例时,正在创建 FormArray
对象
但是,如果您使用 ControlValueAccessor
方法将 FormControl
实例应用于 class,它将写入 FormControl
或 FormGroup
(如果您想要使用 Angular 表单对象提供的)到您传递的控件的值。
因此,在第一种情况下你得到一个 FormArray
对象,在第二种情况下你可以获得常规 JS 类型(对象、数组、字符串等)或 FormGroup
/FormControl
.
如果您想要针对您的案例的更多扩展答案,则需要代码示例,因为您的实现可能会导致在某些时候将数组转换为 FormArray
。
更新 #1
如果我们将 valueChanges
从 users
更改为 form
我们可以看到这种形式有点破损,因为 .value
给了我们另一个 FormArray
而不仅仅是数组。
此外,我已经检查了实现,没有任何地方可以在其中获得常规数组。但是,自定义控件实施错误恕我直言,因为您应该 .value
上的值而不是 FormArray
或与此类似的任何值。
因此,如果您可以更改此控件的实现,我建议您这样做。我以
的方式进行
registerOnChange(fn: any): void {
this.tagsArray.valueChanges.subscribe(fn);
}
我用 ControlValueAccessor 构建了一个自定义输入组件,它非常适合添加标签作为选择。 (Stackblitz)
我的问题是:
- 当我在表单中实现组件时(城市和州控件)
- 通过选择一些选项为两个控件添加值
- 提交表格
- 有时控件值是选定标签的数组(如预期的那样)
- 其他时候它是一个实际的 FormArray 对象
这是提交 angular 表单后同一组件的两个值的屏幕截图。一个是对象数组(预期),另一个是实际的 FormArray 对象,其中 .value 属性 包含对象数组!
如果您不想访问 StackBlitz,这里有一些它如何工作的代码。
自定义控件是这样实现的。
this.form = this.fb.group({
tags: this.fb.array([])
});
当用户选择下拉项或点击回车时,对象保存如下:
get tagsArray(): FormArray { return this.form.get('tags') as FormArray; }
...
this.tagsArray.push(new FormControl(value));
this.onChange(this.tagsArray); // update controller value
您可以像这样(也在我的 StackBlitz 中)通过在我的 StackBlitz 中的 formGroup 中实现该组件来复制它:
表单初始化
public form: FormGroup = this.fb.group({
states: [],
cities: []
});
模板
<input-tags formControlName="cities" label="Cities" [typeAhead]="cities" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
<input-tags formControlName="states" label="States" [typeAhead]="states" [displayKeys]="['name']" filterKeys="['name']"></input-tags>
但问题是:
什么时候Angular的FormArray是传统数组,什么时候是FormArray Array like object?
new FormArray([])
或 formBuilder.array([])
. 创建控件实例时,正在创建 FormArray
对象
但是,如果您使用 ControlValueAccessor
方法将 FormControl
实例应用于 class,它将写入 FormControl
或 FormGroup
(如果您想要使用 Angular 表单对象提供的)到您传递的控件的值。
因此,在第一种情况下你得到一个 FormArray
对象,在第二种情况下你可以获得常规 JS 类型(对象、数组、字符串等)或 FormGroup
/FormControl
.
如果您想要针对您的案例的更多扩展答案,则需要代码示例,因为您的实现可能会导致在某些时候将数组转换为 FormArray
。
更新 #1
如果我们将 valueChanges
从 users
更改为 form
我们可以看到这种形式有点破损,因为 .value
给了我们另一个 FormArray
而不仅仅是数组。
此外,我已经检查了实现,没有任何地方可以在其中获得常规数组。但是,自定义控件实施错误恕我直言,因为您应该 .value
上的值而不是 FormArray
或与此类似的任何值。
因此,如果您可以更改此控件的实现,我建议您这样做。我以
的方式进行registerOnChange(fn: any): void {
this.tagsArray.valueChanges.subscribe(fn);
}