【问题标题】:Angular 2 - Get the value of changed FormControl in ObservableAngular 2 - 在 Observable 中获取更改的 FormControl 的值
【发布时间】:2017-07-28 19:54:12
【问题描述】:

我有一个用FormBuilder 构建的简单表单:

this.contactForm = formBuilder.group({
  'name': [''],
  'email': [''],
  'phone': [''],
});

我想观察每个控件的变化,并在发生这种情况时运行具有更新值的函数:

getContacts(value: any) {
    this.phoneContacts.findContact(value).then(
        contacts => {
            // do something
        }
    );
}

现在,我正在为每个控件执行此操作,使用 bind 访问组件的 this 对象:

this.contactForm.get('name').valueChanges.subscribe(this.getContacts.bind(this));
this.contactForm.get('email').valueChanges.subscribe(this.getContacts.bind(this));
this.contactForm.get('phone').valueChanges.subscribe(this.getContacts.bind(this));

有没有什么方法可以监视更改并仅通过一次订阅获得更新的值?我知道我可以直接订阅this.contact.form,但我得到的不仅仅是更新的控件,而是所有控件的值。

【问题讨论】:

  • 所以如果我理解正确的话,你想要像this.contactForm.subscribeToUpdated() 这样的东西?
  • 没错! subscribetoUpdated() 会给我上次更改输入的值

标签: angular angular2-forms


【解决方案1】:

您可以使用合并运算符将 3 个单独的 observable 合并为一个。这将为您提供一个单独的可观察对象,只要任何一个表单字段值发生更改,它就会发出单个值。

this.contactForm.get('name').valueChanges
    .merge(this.contactForm.get('email').valueChanges)
    .merge(this.contactForm.get('phone').valueChanges)

上述方法的主要问题是您现在不知道哪个值与哪个表单控件对应。一种解决方案是将值更改映射到另一个同时包含值和控件的对象(即值的来源)

// making some local variables for convenience
let name = this.contactForm.get('name')
let email = this.contactForm.get('email'
let phone = this.contactForm.get('phone')

name.valueChanges.map(v => ({control: name,value: v})
    .merge(email.valueChanges.map(v => ({control: email, value: v}))
    .merge(phone.valueChanges.map(v => ({control: phone, value: v}))  

这将提供一个 observable,只要任何字段发生变化,它就会发出,并且它发出的值将是一个包含该值和发出该值的控件的对象。

【讨论】:

    【解决方案2】:

    您可以对单个控件使用 valueChanges 并订阅它:

     this.contactForm.controls['name'].valueChanges.subscribe((value) => {
      console.log(" name : " + value)
    })
    

    【讨论】:

    • 这就是我现在正在做的事情,但我不想为每个FormControl单独做这件事
    • 好的,这样你就可以成为一个合适的 RxJs 操作员并将所有 Observable 合并为一个。
    【解决方案3】:

    您可以从表单中获取所有可观察的控件 valueChanges 并合并所有流:

    const observablesArray = this.contactFrom.controls.map((control) => control.valueChanges);
    
    Observable.merge(...observablesArray).do(console.log).subscribe();
    

    现在,当字段更改时,您会收到一个值,而不是包含所有字段的对象。

    【讨论】:

    • 我无法让它工作。你能创建一个 StackBlitz 吗?这将是答案并且非常有用!
    【解决方案4】:
    ngOnInit() {
        this.contactForm.valueChanges.subscribe(value => {
          console.log(value.name)  
        });
    }
    

    您可以像这样定位单个控件,

    this.contactForm.controls.name.valueChanges.subscribe(value => {
         console.log(value);
    });
    

    【讨论】:

    • 在订阅中,我运行一个函数来获取更新的值并对其进行处理。因此,我需要知道更新了哪个FormControl。可以是其中之一
    • 你更新的答案是我现在已经在做的,除了我必须做三遍。我感兴趣的是我是否可以只订阅整个FormGroup,并且只获得更新的FormControl
    • 我不知道确切的答案,但您可以选择一种解决方法。
    • 是的,你可以。您可以将我的答案用于合并,但您需要以某种方式标记控件以识别它们。例如,您可以使用对象作为值并向该对象注入一些控件 ID。
    猜你喜欢
    • 2020-09-15
    • 2019-07-15
    • 2016-11-05
    • 2017-12-01
    • 2018-07-13
    • 2019-01-25
    • 1970-01-01
    • 2019-03-10
    • 2019-04-27
    相关资源
    最近更新 更多