简体   繁体   English

Angular 无功 forms:变化与值变化

[英]Angular Reactive forms : change vs valueChanges

I am using reactive forms in Angular 7.我在 Angular 7 中使用反应式forms。

I have many fields that are dependent on other fields.我有许多依赖于其他领域的领域。

What I am curious about of what should I use (change) or this.form.get("control_name").valueChanges ?我对我应该使用什么(change)this.form.get("control_name").valueChanges感到好奇?

For ex.例如。 if both will work on inputs then I want to know difference, pros & cons between them.如果两者都适用于输入,那么我想知道它们之间的区别、优缺点。

Which is better with performance?哪个性能更好?

Let's just consider that what you're looking for is to listen to a change on an input tag of type="text"让我们考虑一下您正在寻找的是监听type="text" input标签的变化

In case of valueChangesvalueChanges情况下

Since it is an Observable, it will fire with a new value.由于它是一个 Observable,它将以一个新值触发。 This value will be the changed value of the input field.该值将是input字段的更改值。 And to listen to it, you will have to subscribe to the valueChanges Observable.要收听它,您必须subscribe valueChanges Observable。 Something like this:像这样的东西:

this.form1.controls['name'].valueChanges.subscribe(change => {
  console.log(change); // Value inside the input field as soon as it changes
});

In the case of (change) event(change)事件的情况下

In case of the change event, for input tag, the change event will only fire once you blur away from that input field.在的情况下change情况下,对于input标签,则change事件只会火,一旦你blurinput字段。 Also, in this case, you'll get the $event Object.此外,在这种情况下,您将获得$event对象。 And from that $event Object, you'll have to extract the field value.从那个$event对象中,您必须提取字段值。


So in code, this will look something like this:所以在代码中,这看起来像这样:

import { Component } from '@angular/core';
import { FormGroup, FormBuilder } from '@angular/forms';

@Component({...})
export class AppComponent  {
  name = 'Angular';
  form1: FormGroup;
  form2: FormGroup;

  constructor(private fb: FormBuilder) {}

  ngOnInit() {
    this.form1 = this.fb.group({
      name: [],
      email: []
    });

    this.form2 = this.fb.group({
      name: [],
      email: []
    });

    this.form1.controls['name'].valueChanges.subscribe(change => {
      console.log(change);
    });
  }

  onForm2NameChange({ target }) {
    console.log(target.value);
  }

}

And in the Template:在模板中:

<form [formGroup]="form1">
  <input type="text" formControlName="name">
  <input type="text" formControlName="email">
</form>

<hr>

<form [formGroup]="form2">
  <input type="text" formControlName="name" (change)="onForm2NameChange($event)">
  <input type="text" formControlName="email">
</form>

Here's a Working Sample StackBlitz for your ref.这是供您参考的工作示例 StackBlitz


NOTE: It completely depends on your use case as to which one would be more suitable.注意:这完全取决于您的用例,哪一个更合适。


UPDATE:更新:

For your specific use case, I would suggest using RxJS Operators to get the job done.对于您的特定用例,我建议使用 RxJS Operators 来完成工作。 Something like this:像这样的东西:

zipCodeFormControl
  .valueChanges
  .pipe(
    debounceTime(500),
    distinctUntilChanged(),
    switchMap(
      zipcode => getAddressFromZipcode(zipcode)
    ),
    map(res => res.actualResult)
  )
  .subscribe(addressComponents => {
    // Here you can extract the specific Address Components
    // that you want to auto fill in your form and call the patchValue method on your form or the controls individually
  });

This is case-to-case, but I find that things like checkboxes and radio buttons (true/false type controls) work better with the (change) handler and inputs and textfields are generally more suitable for valueChanges.这是个案,但我发现复选框和单选按钮(真/假类型控件)之类的东西与(更改)处理程序一起使用效果更好,输入和文本字段通常更适合 valueChanges。

Although I'm not sure of performance, I assume this would be the ideal use case when dealing with this decision.尽管我不确定性能,但我认为这将是处理此决定时的理想用例。

A good use case for valueChanges (for everything) is a complex form with a lot of ngIf logic. valueChanges 的一个很好的用例(对于一切)是一个复杂的形式,有很多 ngIf 逻辑。 Sometimes these forms need a "chain reaction" of value changes to work correctly, in which case a (change) handler would be useless有时这些表单需要值更改的“连锁反应”才能正常工作,在这种情况下(更改)处理程序将无用

In case of an input (text) field, I would suggest to use either changeValues or value depending on your use case:对于输入(文本)字段,我建议根据您的用例使用changeValuesvalue

  • If you want to implement something similar to "Google's autocomplete feature", ie, to provide (search) suggestions as you type → then use changeValues .如果您想实现类似于“Google 的自动完成功能”的功能,即在您键入时提供(搜索)建议 → 然后使用changeValues
  • For every other case, I would use change .对于其他所有情况,我都会使用change

This is just a rule of thumb, though, the devil is in the details.然而,这只是一个经验法则,魔鬼在细节中。

Here is the code of a working example which I wrote while doing my own research/testing, it implements both approaches for the sake of comparison:这是我在进行自己的研究/测试时编写的一个工作示例的代码,为了比较,它实现了两种方法:

I would recommend to use Reactive Forms logic only.我建议仅使用反应式 Forms 逻辑。 If you need to have a behaviour like (change) has, so that the value should only be emitted when blur is executed, you can set updateOn: 'blur' like this:如果您需要具有(change)之类的行为,以便仅在执行 blur 时发出该值,您可以像这样设置updateOn: 'blur'

    this.fb.group({
      title: this.fb.control('', { updateOn: 'blur' }),
      description: '',
    })

or like this for the whole form:或者对整个表格这样:

    this.fb.group({
      title: '',
      description: '',
    },{updateOn: 'blur'})

Now you can subscribe to valueChanges:现在您可以订阅 valueChanges:

this.form.valueChanges.subscribe(change=>{ console.log(change) })

This will log changes in description everytime you type something and for title only on leaving the input field when considering the first example.这将记录每次您输入内容时的描述更改,并且仅在考虑第一个示例时离开输入字段时记录标题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM