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

时间:2019-02-21 14:49:19

标签: javascript angular rxjs angular-reactive-forms rxjs6

valueChanges每次setValue(value)函数在FormControl对象上调用时,FormControl对象上存在的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发出的第一个值,因为在创建valueChanges观察值之前已设置了formControl1值。

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。因此,distinctUntilChanged第一次被调用,即第

行:

formControl2.setValue(1)

它将已经具有previousValue(1)来与新值进行比较,因此订阅中的函数将不会执行。

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

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

2 个答案:

答案 0 :(得分:1)

如果我正确理解了这个问题,您希望观察对象仅在除初始值之外的任何值更改时触发?

创建表单控件时是否尝试过设置值

new FormControl({ value: 1 });

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

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

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

  

emitEvent:为true或不提供时(默认值),当控制值更新时,statusChanges和valueChanges可观察对象均发出具有最新状态和值的事件。如果为false,则不会发出任何事件。

我希望这会有所帮助!

答案 1 :(得分:0)

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