【问题标题】:Angular Reactive Form - Form Array - How do I set FormArray with spread operator?Angular Reactive Form - Form Array - 如何使用扩展运算符设置 FormArray?
【发布时间】:2023-03-14 14:03:01
【问题描述】:

我有一个formarray。如果我使用表单构建器对其进行初始化并推动它,它似乎可以正常工作。如果我采用与从中推送项目相同的数组,并尝试使用展开运算符一次将其全部添加,我会收到错误“错误错误:找不到路径的控件:'sizesArray -> 0'”

我的问题是,按照 ngrx/rsjx/功能响应式编程的精神,我怎样才能保持 Formarray '不可变'并从 FormGroup[] 分配给它,而不是清除、循环和推送?

以下是相关代码:

sizesArray: FormArray;
sizesArray2: FormArray;
sizes: Observable<SizeModel[]>;

constructor(
    private productStore: Store<productState.State>,
    private fb: FormBuilder
  ) {
    this.sizes = productStore.select(productState.selectSizes);
  }

ngOnInit() {


    this.sizesArray = this.fb.array([]);
    this.sizesArray2 = this.fb.array([]);

    this.sizes
      .pipe(
        skipWhile(sizes => !sizes),
        map(sizes => {
         return sizes.map(size => this.fb.group({size}));
        }
       )
      )
      .subscribe(
        sizes => {
          // this is the code I want to use.  that throws the error
          this.sizesArray = this.fb.array([...sizes]);

          // this code works, but I don't know how it's different than the code above
          this.sizesArray2.clear();
          sizes.forEach( size => {
            this.sizesArray2.push(size);
          });

        }
      );

    this.sizeForm = this.fb.group({
      sizesArray: this.sizesArray
    });

  }

还有我的模板:

...
<form [formGroup]="sizeForm">
      <fieldset  id="size-container">
        <legend>Sizes</legend>
        <div formArrayName="sizesArray" >
            <div *ngFor="let size of sizesArray.controls; let i = index;" [formGroupName]="i">
            <app-size-form
              formControlName="size"
              (deleteClicked)="deleteSize(i);">
            </app-size-form>
          </div>
        </div>
      </fieldset>
      <button (click)="addSize()" id="size-button">Add Size</button>
      <button mat-button matStepperPrevious>Back</button>
      <button mat-button (click)="submit()">Save</button>
    </form>
...

谢谢!

【问题讨论】:

  • 你不能对像 formGroup 这样复杂的对象使用扩展运算符,(扩展运算符给出“属性”的副本而不是方法,是的,你有,例如“属性”setValue,但不是一个“方法” setValue)。注意:我认为如果你使用 this.fb.array(sizes) 它必须是工作
  • @eliseo - 好点。我打算引入 lodash 的 cloneDeep 来解决它。谢谢!

标签: angular typescript angular-reactive-forms formarray


【解决方案1】:

我认为问题在于您正在更改 引用

this.sizeForm = this.fb.group({
  sizesArray: this.sizesArray
});

此时sizeArray指向this.sizesArray引用的值,即this.fb.array([])。然后,在订阅者的下一个回调中,您将更改引用。这个值也被formControlName='sizesArray'“捕获”,这意味着

<div *ngFor="let size of sizesArray.controls; let i = index;" [formGroupName]="i">

将创建多个FormGroup 实例,它们是容器sizesArray 的子级,该容器为空。

现在,this.sizesArray(您在模板中对其进行迭代)指向其他内容,即:this.fb.array([...sizes])

所以,基本上发生的事情是sizesArraysizeForm 的孩子)指向一个空的FormArray,而this.sizesArray 指向一个非空 FormArray

在这种情况下你可以这样做:

.subscribe(sizes => {
  this.sizeForm.setControl('sizeArray', this.fb.array(sizes))
})

【讨论】:

  • 就是这样。谢谢!我想我认为表单将引用我的 this.sizesArray 变量,而不是该变量的值,所以当我更改它时,我认为表单将继续指向变量并且变量将指向新位置。错误的。我最终将下面的代码:this.sizeForm = this.fb.group({ sizesArray: this.sizesArray }); 移动到一个函数并在 this.fb.array([...sizes]) 之后再次调用它,效果非常好。
  • 很高兴它成功了! Here's 一篇深入探讨 Angular 表单的文章,如果您想了解更多关于它们的有趣信息!
  • 从那以后我对此做了更多的研究,我猜想来自 C# 背景的事实是,在 javascript 和 typescript 中,对象是通过引用传递的,但是对对象的引用是传递的按价值得到我。这真的很违反直觉,我仍然在思考它。这个问题的答案也给了我一些真正的见解:stackoverflow.com/questions/518000/…
  • 感谢分享! but references to objects are passed by value我不确定这是不是真的。他们在我看来,sizesArray 指向[]。而[]sizeForm 使用。然后sizesArray 指向另一个数组[...sizes],所以初始的[] 不可能被更新。
猜你喜欢
  • 2021-05-30
  • 1970-01-01
  • 2023-03-07
  • 1970-01-01
  • 2021-06-04
  • 2020-12-19
  • 1970-01-01
  • 2019-11-21
  • 2021-05-02
相关资源
最近更新 更多