【问题标题】:Dynamically update form values in a FormArray using valueChanges使用 valueChanges 动态更新 FormArray 中的表单值
【发布时间】:2019-09-16 17:35:39
【问题描述】:

我知道我们可以在 FormArray 上使用 valueChanges 并在键入时查看更改。我的问题很直接:如何在 valueChanges 中执行array.at(i).patchValue?我需要知道我键入值的行的索引并更新FormControls。我想要实现的是例如在计算器中,我想在添加两个数字时动态显示值,而无需在输入字段之外单击。

ngOnInit() {
  this.form = this.fb.group({
    fdnUnitPrice: [''],
    cap_values: this.fb.array([this.fb.group({
      name: '',
      fdnTotalShare: '', 
      fdnVal: '',
    }
    )])
  })
  this.onValChanges();
}

onValChanges(): void {
  this.capValues.valueChanges.subscribe(val => {
    console.log(val.length)
  })
}

在我上面的代码中,fdnVal 中的结果应该是什么,当我将fdnUnitPricefdnTotalShare 相乘时,它应该显示值。下一行fdnTotalShare 的值可能不同,因此fdnVal 应该不同。

【问题讨论】:

标签: angular angular-reactive-forms


【解决方案1】:

我不会将valueChanges 用于formarray,而是使用在用户输入时调用的函数。由于单价也是可编辑的,我们可以在上面使用相同的功能。所以我建议如下:

在模板中:

<input type="number" formControlName="fdnTotalShare" (input)="calculate(cap)"/>

cap 来自哪里:*ngFor="let cap of capValues.controls;"&gt;

和功能:

calculate(cap) {
  cap.get('fdnVal').setValue(
    this.form.get('fdnUnitPrice').value * cap.get('fdnTotalShare').value 
  )
}

然后我们将实际监听单价表单控件的valueChanges,然后我们在其中迭代表单数组,并为每个表单组调用calculate 函数:

onValChanges(): void {
  this.form.get('fdnUnitPrice').valueChanges.subscribe((val) => {
    this.capValues.controls.forEach(cap => {
      this.calculate(cap);
    })
  })
}

演示:STACKBLITZ

PS:组件销毁时记得退订valuChanges

【讨论】:

    【解决方案2】:

    当您有多个时,您正在分配给单个表单数组,我希望您可以在那一刻捕获索引并将其绑定到您的值更改函数

    this.myForm = this.fb.group({
      arr1: this.fb.array([this.fb.group({name: [''],pay: ['']})]),
      arr2: this.fb.array([this.fb.group({name: [''],pay: ['']})])
    });
    
    // binding index with array index
    Object.keys(this.myForm.controls).forEach((item, index) => {
      this.myForm.controls[item].valueChanges.subscribe(value => {
        this.myForm.controls[item].patchValue([{name:value[0].pay + 'xxx'}], {emitEvent: false, onlySelf: true})
        console.log({index,value})
      });
    });
    

    进入无限循环的问题。如果通过代码而不是用户进行更新,我们必须阻止 valuechanges 触发,我们可以通过将此 {emitEvent: false, onlySelf: true} 作为第二个参数传递给 patchValue 来做到这一点,它不会触发 valuechanges。

    stackblitz 供您参考https://stackblitz.com/edit/angular6-dynamic-form-array-5by4ud

    【讨论】:

    • 嗨,我已经尝试过了,但出现错误Maximum call stack size exceeded。我在subscribe 之后添加了patchValue valueChanges
    • 补丁值将再次调用 valuechanges。你想做什么 ??如果已经打了补丁,你能制作条件路径吗?你会知道的,所以不要再打补丁了
    • 我想动态显示值而不点击输入框。所以随着fdnTotalShares的数字变化,fdnVal也应该相应变化
    • 好的,因此您可以在每次用户输入可能隐藏的控件时重置一个标志,并且当您修补值时,在每一行中查找该控件并在下次设置值时设置它不要修补值,这意味着值更改是由于补丁而触发,否则如果值被重置,则意味着用户已更新 ui
    • 你能根据你的建议做一个stackblitz吗?
    猜你喜欢
    • 2021-04-15
    • 2018-05-21
    • 2017-11-16
    • 2023-02-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-25
    • 1970-01-01
    相关资源
    最近更新 更多