Angular中的FormArray何时是传统数组,何时是FormArray对象?

10

我使用ControlValueAccessor构建了一个自定义输入组件,可以很好地添加标签作为选择项。(Stackblitz

我的问题是:

  1. 当我在表单中实现该组件(城市和州控件)时
  2. 通过选择某些选项向两个控件添加值
  3. 提交表单
  4. 有时控件值是所选标签的数组(如预期的那样)
  5. 其他时候它是一个实际的FormArray对象

这是相同组件的两个值在提交angular表单后的截图。一个是对象数组(预期的),另一个是实际的FormArray对象,其中.value属性包含对象数组!

enter image description here

如果您不想访问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 中的 formGroup 中实现该组件来复制它(也可以在我的 StackBlitz 中进行操作)。
表单初始化。
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 的数组对象?

1个回答

3

当您使用new FormArray([])formBuilder.array([])创建控件实例时,会创建FormArray对象。

但是,如果您将一个FormControl实例应用于带有ControlValueAccessor方法的类,则它将把FormControlFormGroup(如果您想要使用Angular提供的表单对象)写入您传递的控制的值中。

因此,在第一种情况下,您将获得一个FormArray对象,在第二种情况下,您可以获得常规JS类型(对象、数组、字符串等)或FormGroup/FormControl

如果您想要更详细的答案来特定于您的情况,则需要代码示例,因为您的实现可能在某个时刻将数组转换为FormArray

更新#1

如果我们将valueChangesusers更改为form,我们会发现这个表单有点错误,因为.value给我们的是另一个FormArray而不仅仅是数组。

enter image description here

另外,我已经检查了实现,在那里您无法获取常规数组。但是,自定义控件的实现方式在我看来是错误的,因为您应该在.value上获得值,而不是FormArray或类似于此的东西。

因此,如果您可以更改此控件的实现方式,我建议您这样做。我以以下方式实现:

registerOnChange(fn: any): void {
  this.tagsArray.valueChanges.subscribe(fn);
}

1
谢谢@Sergey,这很有见地。但是这个控件在同一个表单中实现了两次完全相同的方式,它们有时候具有[]值,有时候具有FormArray{}值,就像屏幕截图所示的那样。 - Ben Racicot
在这种情况下,我建议您使用IDE调试工具检查代码,以查看值何时转换。只需在分配给控件的每个值处设置断点,您就应该能找到它。 - Sergey
是的,初始值是一个数组,补丁值也是数组,但选择选项会创建FormArray值。添加的任何值都通过相同的addTag方法进行处理。这就是为什么这没有意义的原因。您能否更详细地解释一下您建议的registerOnChange重构?顺便说一句,谢谢您。 - Ben Racicot
@BenRacicot 这只是 ControlValueAccessor 的基本方法,用于定义应获取值以将其分配给主表单的函数。有关更多信息,请阅读此处 https://angular.io/api/forms/ControlValueAccessor - Sergey
1
个人而言,我认为将 FormArray 对象推入主表单中没有意义,因为它会破坏逻辑并引起一些问题。当我实现这些 ControlValueAccessor 时,我只使用简单的值(即不是 AbstractControl 的子类),一切都工作得很好。 - Sergey
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接