只有在表单控件的先前值!==表单控件的当前值时,角度订阅才会更改

问题描述

仅当输入/选择的先前值!=输入/选择的当前值时,我才想调用onDataChange()。

但是我注意到,只要将光标放在输入字段上,它仍在调用onDataChange()(但没有更改输入字段的任何值/更改了下拉值的选择)。

我使用过成对的startWith(null),然后使用filter(prev!= next),但即使前一个值与下一个值相同,它仍然会执行onDataChange()。

主要问题是当将光标放在输入字段上但不更改任何值时,它仍然调用onDataChange()。

仅当输入值发生变化/下拉选择项发生变化时,我才想调用onDataChange()。 onDataChange()将调用api调用,这可能需要更长的时间来检索结果。

有人遇到类似的问题并且可以提供指导吗?谢谢。

'

  <form class="form" [formGroup]="numberForm" novalidate [style.width.px]="width">
       <select name="types" id="dropdown-number-types" formControlName="dropdown">
           <option *ngFor="let type of types" [value]="type">{{type}}</option>
       </select>
    
       <input id="onValue" type="text" name="onValue" formControlName="onValue">
       <select name="equalsUnit" id="dropdown-number-unit" formControlName="onValueUnit">
            <option *ngFor="let unit of units" [value]="unit">{{unit}}</option>
       </select>
</form>

ngOnInit() {
  const valueChanges: Observable<any>[] = [
    this.numberForm.get('dropdown').valueChanges,this.numberForm.get('onValue').valueChanges,this.numberForm.get('onValueUnit').valueChanges
  ].map(obs =>
      obs.pipe(
          startWith(null),pairwise(),filter(([prev,next]) => prev !== next),)
  );

  // Merge all valueChanges observables into one - and debounce time for 250ms to avoid processing
  // events in quick succession which can happen if user is changing values quite fast in UI.
  merge(...valueChanges)
  .pipe(
      takeuntil(this.ngUnsubscribe),debounceTime(this.delay)
  )
  .subscribe(([prev,next]: [any,any]) => {
      this.onDataChange();
  });
  this.updateValidators();
  super.ngOnInit();
}

如果我删除合并并仅监视'onValue'的formcontrolname的更改,则仅当值存在差异时,它才会执行onDataChange()。

有没有其他方法可用于合并这三个formcontrolname并监视任何formcontrolname的更改?

解决方法

如果理解正确,您需要distinctUntilChanged运算符,这就是我重构代码的方式:

const valueChanges: Observable<any>[] = [
  this.numberForm.get('dropdown').valueChanges,this.numberForm.get('onValue').valueChanges,this.numberForm.get('onValueUnit').valueChanges
].map(obs => obs.pipe(startWith(null)));

combineLatest(valueChanges).pipe(
  debounceTime(this.delay),distinctUntilChanged((prev,curr) =>
    prev[0] === curr[0] && prev[1] === curr[1] && prev[2] === curr[2]
  ),takeUntil(this.ngUnsubscribe),).subscribe(() => {
  this.onDataChange();
});

注意:

  • 我正在使用combineLatest,因为merge将在开始时发出3个单独的事件,而combineLatest将在开始时发出1个组合的事件。之后,combineLatest会在每次更改时发出,并为您提供3个可观察值的更新组合值,其中merge仅给您一个更新值,而不是组合值。
  • 使用distinctUntilChanged将新的合并值与先前的合并值进行比较。我专门将其放在debounceTime之后,因为您需要将新的去抖动值与旧的去抖动值进行比较。