angular 仅当表单控件的先前值 !== 表单控件的当前值时才订阅更改
angular subscribe to changes only if previous value of the form control !== currentvalue of the formcontrol
仅当输入/选择的先前值 != 输入/选择的当前值时,我才想调用 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()。
是否有任何替代方法可用于合并这 3 个 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 个 Observables 的更新组合值,其中 merge
只会为您提供一个更新值而不是组合值。
- 使用
distinctUntilChanged
将新的合并值与之前的合并值进行比较。我特意把它放在 debounceTime
之后,因为你需要比较新的去抖值和旧的去抖值。
仅当输入/选择的先前值 != 输入/选择的当前值时,我才想调用 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()。
是否有任何替代方法可用于合并这 3 个 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 个 Observables 的更新组合值,其中merge
只会为您提供一个更新值而不是组合值。 - 使用
distinctUntilChanged
将新的合并值与之前的合并值进行比较。我特意把它放在debounceTime
之后,因为你需要比较新的去抖值和旧的去抖值。