【问题标题】:When is Angular's FormArray a traditional array and when is it a FormArray object?Angular 的 FormArray 什么时候是传统数组,什么时候是 FormArray 对象?
【发布时间】:2023-03-05 22:32:02
【问题描述】:

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

我的问题是:

  1. 当我在表单中实现组件时(城市和州控制)
  2. 通过选择一些选项为两个控件添加值
  3. 提交表格
  4. 有时控制值是一个选定标签的数组(如预期的那样)
  5. 其他时候它是一个实际的 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 中的 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 类似对象的数组?

【问题讨论】:

    标签: javascript angular forms formarray


    【解决方案1】:

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

    但是,如果您将 FormControl 实例应用于具有 ControlValueAccessor 方法的类,它将写入 FormControlFormGroup(如果您想使用 Angular 表单对象提供)来控制您的值已经过去了。

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

    如果您想要针对您的案例的更多扩展答案,则需要代码示例,因为您的实现可能会导致在某些时候将数组转换为 FormArray

    更新 #1

    如果我们将valueChangesusers 更改为form,我们可以看到这种形式有点损坏,因为.value 给了我们另一个FormArray 而不仅仅是数组。

    另外,我已经检查了实现,没有任何地方可以在其中获得常规数组。但是,恕我直言,自定义控件的实现是错误的,因为您应该使用 .value 而不是 FormArray 或类似的值。

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

    的方式做
    registerOnChange(fn: any): void {
      this.tagsArray.valueChanges.subscribe(fn);
    }
    

    【讨论】:

    • 感谢@Sergey,这很有见地。但是这个控件以完全相同的方式以相同的形式实现了两次,它们有时具有[] 值,有时具有FormArray{} 值,如值屏幕截图所示。
    • @BenRacicot 在这种情况下,我建议您使用 IDE 调试工具检查您的代码,以查看您的值在哪里转换。只需在分配给控制的值的任何地方都设置断点,您应该会找到它。
    • 是的,初始值是一个数组,补丁值是数组,但是选择一个选项会创建FormArray 值。添加的任何值都通过相同的addTag 方法。这就是为什么这没有意义。你能解释更多关于你推荐的 registerOnChange 重构吗?感谢这个顺便说一句。
    • @BenRacicot 这只是ControlValueAccessor 的一个基本方法,用于定义应该获取值以将它们分配给主窗体的函数。有关它的更多信息,您可以在此处阅读angular.io/api/forms/ControlValueAccessor
    • @BenRacicot 我个人认为将 FormArray 对象推入主窗体没有意义,因为它会破坏逻辑并导致一些问题。当我实现这些 ControlValueAccessor 时,我只使用简单的值(意味着不是AbstractControl 后代),一切都很好。
    猜你喜欢
    • 2019-11-24
    • 1970-01-01
    • 1970-01-01
    • 2019-10-17
    • 1970-01-01
    • 2012-01-08
    • 2017-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多