繁体   English   中英

在 Angular2+ 中订阅 FormControl 真实值更改的最佳方法?

[英]Best way to subscribe to true value changes of FormControl in Angular2+?

每次在 FormControl 对象上调用setValue(value)函数时,存在于 FormControl 对象上的valueChanges Observable 都会发出值。

使用 RxJS 操作符distinctUntilChanged我们可以过滤掉不是新的值。 但是如果 FormControl 具有初始值,这将不起作用。

const formGroup1 = new FormGroup({page: new FormControl(1)});
const formControl1 = formGroup1.get('page');
formControl1.valueChanges.pipe(distinctUntilChanged())
  .subscribe(v => console.log(`new formControl1 value: ${v}`));
formControl1.setValue(1);
formControl1.setValue(2);

这将记录

> new form1Control value: 1
> new form1Control value: 2

1 是valueChanges Observable 发出的第一个值,因为 formControl1 值是在valueChanges Observable 创建之前设置的。

distinctUntilChanged永远不会过滤掉第一个发出的值

这是此问题的一种解决方案:

const formGroup2 = new FormGroup({page: new FormControl(1)});
const formControl2 = formGroup2.get('page');
formControl2.valueChanges.pipe(
    startWith(1),
    distinctUntilChanged(),
    skip(1)
).subscribe(v => console.log(`new formControl2 value: ${v}`));
formControl2.setValue(1);
formControl2.setValue(2);

在这里,我通过发出 FormControl 初始值来修改valueChanges Observable,然后跳过它。 所以第一次调用distinctUntilChanged时,这是一行:

formControl2.setValue(1)

它已经有 previousValue (1) 来比较新值,所以 subscribe 中的函数不会被执行。

但我真的不喜欢这个解决方案。 是否有内置或推荐的方法来处理 Angular7 和 RxJS6 中的 FormControl 值更改?

stackblitz: https ://stackblitz.com/edit/angular-arevmw ? file = app%2Ficon-overview-example.ts

如果我正确理解了这个问题,您是否希望您的 observable 仅在初始值以外的任何值更改时触发?

您是否尝试在创建表单控件时设置该值

new FormControl({ value: 1 });

或者您可以指定在设置值时不想发出事件

const formControl1 =new FormControl(1); formControl1.setValue(1, { emitEvent: false });

根据文档,您可以在设置值时指定选项,包括:

发射事件:当为 true 或未提供时(默认值),statusChanges 和 valueChanges observables 都会在控件值更新时发出具有最新状态和值的事件。 如果为 false,则不发出任何事件。

我希望这有帮助!

distinctUntilChanged 初始状态始终为空。 但是当发出第一个值时 distinctuntilchanged 存储的第一个值。 然后发出第二个值后,比较新值和存储的值。 所以您的解决方案是正确的,或者您可以使用 skipWhile 进行第一个值比较。

暂无
暂无

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

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