多个组件绑定相同的响应式控件更新问题

时间:2018-04-19 08:07:21

标签: angular angular-reactive-forms

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

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

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

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

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

是否有一种优雅的方式来处理角度反应形式的情况?

3 个答案:

答案 0 :(得分:7)

一个不需要添加任何(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

答案 1 :(得分:1)

我仅使用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的选项参数,这将防止对valueChanges的回溯执行,直到溢出为止。

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

答案 2 :(得分:0)

我寻找了一个通用的解决方案:我使用 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);
    } 
  }
);