Joh*_*lly 3 validation asynchronous operators rxjs angular-reactive-forms
当我出于某种原因按下表单输入上的按键时,异步验证器不会检测到distinctUntilChanged,并且它仍然发送API请求。例如,如果我按 35,删除 5,然后再次添加 5,它仍然会发送请求。这是代码:(我已经尝试了几乎所有方法,但仍然不起作用)
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
this.isSubmitBtnDisabled = true;
return control.valueChanges.pipe(
debounceTime(1000),
distinctUntilChanged(),
switchMap((value) => {
return this.apiService.someApiRequest({ 'to_number': control.value }).pipe(
map(res => {
console.log(res);
if (res.success) {
// console.log(res);
this.isSubmitBtnDisabled = false;
return null;
} else {
// console.log(res);
this.isSubmitBtnDisabled = true;
return{ 'invalidCharacters': true };
}
}),
);
}),
first()
);
}
Run Code Online (Sandbox Code Playgroud)
默认情况下,validateSomeNumber每次值更改后都会调用。
如果您在每次值更改时返回此值
return control.valueChanges.pipe(
debounceTime(1000),
distinctUntilChanged(),
...
)
Run Code Online (Sandbox Code Playgroud)
您正在为每个值变化创建一个新的可观察值变化。例如,如果您输入四个字符,您最终会得到四个独立的 Observable,每个 Observable 发出一个字符,而不是一个 Observable 发出四次。因此debounceTime和distinctUntilChanged只会影响您在特定值变化时创建的 Observable,但不会影响整个值变化过程。如果它们只影响 Observable 的发射,那么它们显然不会按照您的预期工作。
你应该直接返回http请求
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
this.isSubmitBtnDisabled = true;
return this.apiService.someApiRequest({ 'to_number': control.value }).pipe(
map(..),
);
}
Run Code Online (Sandbox Code Playgroud)
选项 1:更新
为了防止每次值更改时都执行 http 请求,Angular 建议将updateOn属性更改为submit或blur。
使用模板驱动的表单:
<input [(ngModel)]="name" [ngModelOptions]="{updateOn: 'blur'}">
Run Code Online (Sandbox Code Playgroud)
对于反应形式:
new FormControl('', {updateOn: 'blur'});
Run Code Online (Sandbox Code Playgroud)
{updateOn: 'blur'}仅当您的输入失去焦点时才会执行验证器。
选项 2:模拟 debounceTime 和distinctUntilChanged
如果表单值发生变化,Angular 会自动取消订阅 AsyncValidator 返回的上一个 Observable。这允许您使用 进行debounceTime仿真timer。要进行模拟,distinctUntilChanged您可以跟踪最后一个请求术语并自行进行相等性检查。
private lastRequestTerm = null;
validateSomeNumber(control: FormControl): Observable<any> | Promise <any> {
this.isSubmitBtnDisabled = true;
// emulate debounceTime
return timer(1000).pipe(
// emulate distinceUntilChanged
filter(_ => control.value != this.lastRequestTerm),
switchMap(() => {
this.lastSearchTerm = control.value;
return this.apiService.someApiRequest({ 'to_number': control.value });
}),
map(..)
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1293 次 |
| 最近记录: |