【问题标题】:angular subscribe to changes only if previous value of the form control !== currentvalue of the formcontrol仅当表单控件的先前值!==表单控件的当前值时,角度订阅才会更改
【发布时间】:2021-01-13 18:37:00
【问题描述】:

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

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

我已经使用 startWith(null)、pairwise,然后 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()。

我可以使用任何替代方法来合并这 3 个 formcontrolname 并观察任何 formcontrolname 的更改吗?

【问题讨论】:

    标签: rxjs observable angular8 angular-pipe rxjs-observables


    【解决方案1】:

    如果理解正确,您需要 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 个 Observables 的更新组合值,其中merge 将只为您提供一个更新值,而不是组合。
    • 使用distinctUntilChanged 将新的组合值与之前的组合值进行比较。我特地把它放在debounceTime 之后,因为你需要比较新的去抖值和旧的去抖值。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-06-02
      • 1970-01-01
      • 2021-03-22
      • 1970-01-01
      • 2019-10-30
      • 2017-12-07
      • 2023-02-17
      • 2019-10-29
      相关资源
      最近更新 更多