在Angular 2中订阅valueChanges的正确方法

问题描述:

我一直在Angular 2中处理反应表单和valueChanges订阅。我不明白为什么某些形式的订阅似乎不被允许。在Angular 2中订阅valueChanges的正确方法

this.form.get('name').valueChanges /* <- doesn't work */ 
    .do(changes => { 
    console.log('name has changed:', changes) 
    }); 
    .subscribe(); 

this.form.get('title').valueChanges.subscribe(/* <- does work */ 
    changes => console.log('title has changed:', changes) 
); 

This plunker重现问题(开放DevTools控制台看到错误):

ZoneAwareError {stack: "Error: Uncaught (in promise): TypeError: Cannot se…g.com/[email protected]/dist/zone.js:349:25) []", message: "Uncaught (in promise): TypeError: Cannot set prope…ore.umd.js:8486:93)↵ at Array.forEach (native)", originalStack: "Error: Uncaught (in promise): TypeError: Cannot se…ps://unpkg.com/[email protected]/dist/zone.js:349:25)", zoneAwareStack: "Error: Uncaught (in promise): TypeError: Cannot se…g.com/[email protected]/dist/zone.js:349:25) []", name: "Error"…}

在上述第一图案(与do)不是非法确实?

+0

为什么'do'是非法的?您不需要,您可以将回调传递给'subscribe(...)'。 Plunker并没有为我运行(不知道为什么,有一段时间以来,因此无法调查) –

+0

这正是我困惑的问题:为什么它会是非法的? Plunkr并不总是喜欢我 - 我正在用DevTools的错误更新我的帖子。 – user776686

+0

您的Plunker确实错过了“do”操作符的导入。另见http://*.com/questions/34515173/angular-2-http-get-with-typescript-error-http-get-map-is-not-a-function-in/34515276#34515276 –

这使您plunker工作:

  1. 在app.ts
import 'rxjs/add/operator/do'; 
  1. 删除分号之后。做语句添加此import语句
  2. .do(changes => { console.log('name has changed:', changes) })

    C omplete改变app.ts

    import {Component, NgModule, OnInit} from '@angular/core' 
    import {BrowserModule } from '@angular/platform-browser' 
    import { FormGroup, FormBuilder, Validators, ReactiveFormsModule, FormsModule } from '@angular/forms'; 
    import { Observable } from 'rxjs/Observable'; 
    import { Subscription } from 'rxjs/Subscription'; 
    import 'rxjs/add/operator/do'; 
    
    @Component({ 
        selector: 'my-app', 
        template: ` 
        <form novalidate [formGroup]="form"> 
         <div> 
         <select type="text" class="form-control" name="title" formControlName="title"> 
          <option *ngFor="let title of titles" value="{{title}}">{{title}}</option> 
         </select> 
         </div> 
         <div> 
         <input type="text" class="form-control" name="name" formControlName="name"> 
         </div> 
         <fieldset formGroupName="address"> 
         <legend>Address</legend> 
         <input type="text" class="form-control" name="street" formControlName="street"> 
         <input type="text" class="form-control" name="city" formControlName="city"> 
         </fieldset> 
        </form> 
        `, 
    }) 
    export class App implements OnInit { 
        private form: FormGroup; 
        private titles: string[] = ['Mr', 'Mrs', 'Ms']; 
    
        constructor(private fb: FormBuilder){ 
    
        } 
        ngOnInit() { 
        this.form = this.fb.group({ 
         title: 'Mr', 
         name: '', 
         address: this.fb.group({ 
         street: '', 
         city: '' 
         }) 
        }); 
    
        this.form.get('name').valueChanges 
         .do(changes => { 
         console.log('name has changed:', changes) 
         }) 
         .subscribe(); 
    
        this.form.get('title').valueChanges.subscribe(
         changes => console.log('title has changed:', changes) 
        ); 
    
        this.form.get('address').valueChanges.subscribe(
         changes => console.log('address has changed:', changes) 
        ); 
        } 
    } 
    
    @NgModule({ 
        imports: [ BrowserModule, FormsModule, ReactiveFormsModule ], 
        declarations: [ App ], 
        bootstrap: [ App ] 
    }) 
    export class AppModule {} 
    

    另一种解决办法是使用“ngModelChange”事件在你的模板

    更改此:

    <input type="text" class="form-control" (ngModelChange)="doNameChange($event)" name="name" formControlName="name"> 
    

    在您的组件,那么你处理你的更改事件:

    doNameChange(event: any){ 
        alert("change") 
    } 
    
开始=>
+0

谢谢,但正如您所见,我确实知道处理这些更改的一种工作方式。问题的关键是为什么一个合法的模式似乎不起作用。 – user776686

+0

你为什么要用“做”?如果您将功能从“do”移动到正在使用的订阅模块 – Karl

我也有这个问题。

我想在我的情况下做debounceTime,所以它没有解决我的需求。

我其实忘了订阅!

但我能得到价值变动激活也这样说:在角文档从这里

this.form.get('name').valueChanges.forEach(
    (value) => {console.log(value);}) 

来源:hero-detail-component.ts