在FormGroup中订阅输入FormControl的valueChanges

70
在Angular 4中,我正在尝试订阅FormControl的valueChanges。以下两个版本都无法正常工作。我没有看到任何错误。随着我的输入,表单值的JSON正在更新,但订阅并未起作用。
myForm: FormGroup;
public firstName = new FormControl();
public lastName = new FormControl();

this.myForm = this.formBuilder.group({ 
      firstName: '',
      lastName: '',
});

this.myForm.controls.firstName.valueChanges.subscribe(value => {
      console.log(value);
});


this.myForm.get('firstName').valueChanges.subscribe(value => {
      console.log('name has changed:', value)
});

这是一个模板片段示例。

<form #myForm="ngForm">

<md-input-container>
    <input mdInput name="firstName" [(ngModel)]="firstName" placeholder="enter name"/>
</md-input-container>
{{ myForm.value | json }}

虽然下面的答案是正确的,但你可能需要使用 RxJS 函数,如 debounceTime 和 distinctUntilChanged 来提高性能和可用性。此外,在 ngOnDestroy 中需要取消订阅输入监听器。 - ONE_FE
3个回答

88

我认为你在使用 formGroupformControlName 方面缺少了一些东西,应该这样做:

myForm: FormGroup;
firstName = '';
lastName = '';

ngOnInit

this.myForm = this.formBuilder.group({
    firstName: [this.firstName],
    lastName: [this.lastName]
});

this.myForm.controls['firstName'].valueChanges.subscribe(value => {
  console.log(value);
});

HTML

<form [formGroup]="myForm">
   ...

  <input name="firstName" [(ngModel)]="firstName" formControlName="firstName" placeholder="enter name"/>


  <input name="lastName" [(ngModel)]="lastName" formControlName="lastName" placeholder="enter last name"/>

   ...
</form>

谢谢。我放弃了使用formGroup和formBuilder,而是直接使用<input mdInput [formControl]="firstName">。 - beachCode

21

在您的代码中缺少一些关键要素。首先,您试图订阅的内容不存在。您未将该字段标记为formcontrol,因此Angular不知道要订阅该内容。您需要标记formControlName="firstname"以告诉Angular它是一个表单控件。

另外,您还未将表单标记为一个表单组,应该这样写:

<form [formGroup]="myForm">

在表单中使用ngModel是不被鼓励的,甚至在ReactiveFormsModule中也没有包含ngModel指令。我还注意到当与响应式表单一起使用时,它经常会导致问题。你已经有了表单控件来替换ngModel的使用,所以请放弃它并利用表单控件,因为它们已经就位! :)

那么,我会建议在模板中使用某些更改事件而不是valueChanges,但这取决于您自己。

因此,构建表单应该像这样:

this.myForm = this.formBuilder.group({
  firstname: [''],
  lastname: ['']
})
// I like to use variables
this.firstNameCtrl = this.myForm.get('firstname')

// as mentioned, like to use change event:
logValue(value) {
  console.log(value)
}    

模板将会如下所示:

<form [formGroup]="myForm">
  <md-input-container>
    <input mdInput formControlName="firstname" 
         (keyup)="logValue(firstNameCtrl.value)" />
  </md-input-container>  
  <md-input-container>
    <input mdInput formControlName="lastname"/>
  </md-input-container>   
</form>

所以如前所述,请使用表单控件。如果您需要初始值,请在构建表单时设置它们。您可以在表单对象中获取所有值,如果需要,可以访问这些值。


19

我放弃了FormGroup和FormBuilder,只使用了HTML:

HTML:

<input mdInput [formControl]="firstName"> 

应用程序类:

firstName = new FormControl();

ngOnInit:

this.firstName.valueChanges.subscribe(value => {
     console.log('name has changed:', value)
});

我的测试目前无法正常运行,出现错误“未提供 NgControl”,但我会接下来处理它。 更新:我只需要在 TestBed 中导入 ReactiveFormsModule。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接