问题描述
仅当输入/选择的先前值!=输入/选择的当前值时,我才想调用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
之后,因为您需要将新的去抖动值与旧的去抖动值进行比较。