【问题标题】:Multiple components binding with the same reactive form control update issue多个组件绑定同一个响应式表单控件更新问题
【发布时间】:2018-09-29 15:36:21
【问题描述】:

在某些情况下,我们可能需要将多个表单组件绑定到同一个表单控件。而且我对处理这种情况的角度方式感到困惑:

当改变其中一个组件的值时,表单的值会改变,但不会改变其他组件的值。

我在这种情况下所做的解决方法是使用表单值修补 from,这很难看:

this.form.patchValue(this.form.value);

Here is a stackblitz demo for my issue,我添加了输入更改的解决方法,而不是选择以便更好地理解。

有没有一种优雅的方式来处理带有角度反应形式的这种情况?

【问题讨论】:

  • 您尝试过使用.setValue() 吗?你也可以分享你的表单代码吗?因为没有它就很难提供帮助
  • @CruelEngine 问题中已经有一个 stackblitz 代码链接。
  • 作为替代方法,您可以为两个字段设置[(ngModel)] 并将它们绑定到同一个变量,如下所示:stackblitz.com/edit/…

标签: angular angular-reactive-forms


【解决方案1】:

不需要添加任何(change) 侦听器的一个很好的反应式解决方案是创建两个单独的名称控件,并通过订阅valueChanges 流来保持它们同步。

component.ts

import { Component, NgModule, ViewChild } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormBuilder, FormControl, FormGroup } from '@angular/forms';

@Component({
  selector: 'my-app',
  templateUrl: 'app.component.html'
})
export class AppComponent {
  form: FormGroup;

  constructor(private fb: FormBuilder) {
    this.form = this.fb.group({
      nameText: '',
      nameSelect: '',
    })

    const text = this.form.get('nameText');
    const select = this.form.get('nameSelect');

    text.valueChanges.subscribe(v => select.setValue(v, { emitEvent: false }));
    select.valueChanges.subscribe(v => text.setValue(v, { emitEvent: false }));
  }

}

component.html

<form [formGroup]="form">
  When you change the input, the select changes : <br>
  <input type="text" formControlName="nameText"><br>
  When you change the select, the input does not change : <br>
  <select formControlName="nameSelect">
    <option value="value1">value1</option>
    <option value="value2">value2</option>
  </select>
</form>

Live demo

【讨论】:

    【解决方案2】:

    我通过使用 AbstractControl 解决了它 valueChanges 和 setValue API。在这种方法中,您不必使用 2 个单独的表单控件,您可以将任意数量的组件绑定到同一个响应式表单控件。

    this.form.get('formControlName').valueChanges.subscribe(value => {
        this.form.get('formControlName').setValue(value, { onlySelf: true, emitEvent: false, emitModelToViewChange: true });
      }, error => {}, () => { });
    

    这里的关键是setValue的options参数,这将防止valuesChanges的递归执行直到溢出。

    { onlySelf: true, emitEvent: false, emitModelToViewChange: true }
    

    【讨论】:

    • 别忘了退订!特别是如果这个表单会在你的应用程序中显示很多 - 你最终会得到内存泄漏。
    【解决方案3】:

    我寻找了一个通用的解决方案:我使用 JSON var "prevData" 来记住以前的值,而不是无限循环:

    this.prevData = "";
    
    this.form.valueChanges.subscribe( 
      
      data => {  
        let str = JSON.stringify(data); 
        if (str != this.prevData){
          this.prevData = str;
          this.form.patchValue(data);
        } 
      }
    );
    

    【讨论】:

    • 这在我看来不是一个好的解决方案。你为什么不使用{ emitEvent: false } 选项?
    猜你喜欢
    • 2020-04-28
    • 1970-01-01
    • 2019-03-18
    • 2012-12-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-29
    • 2019-04-15
    相关资源
    最近更新 更多