自定义Async校验表单提交时处于PENDING状态该如何处理?
问题根源
- 你的异步校验函数写法存在缺陷:
AsyncValidatorFn应当直接基于当前控件的value返回校验流,你现在依赖valueChanges,如果提交时控件值未发生新的变更,valueChanges不会触发,会导致校验一直处于pending状态。 - 你在
save方法中同步判断表单valid状态,此时异步校验还未执行完成,表单处于pending状态时valid属性固定为false,自然会触发校验失败的提示。
方案1:保留异步校验,等待执行完成(推荐)
先修正异步校验函数的写法,再监听表单状态变化,等异步校验全部结束后再判断有效性,完全保留你现有的循环校验逻辑:
// 修正后的异步校验函数,直接基于当前值校验,不依赖valueChanges checkUniqueProxy(): AsyncValidatorFn { return (control: AbstractControl) => { // 空值直接返回校验通过,可根据自己的业务调整 if (!control.value) { return of(null); } // 直接用当前值发起请求,保留防抖逻辑避免频繁请求 return of(control.value).pipe( debounceTime(1000), switchMap(value => this.api.get('My_API_ENDPOINT', {proxy: value})), map((data:any) => { return data?.unique ? null : {uniqueError: true}; }), first() ) } } // 修改后的save方法,原有循环逻辑完全保留 save(): void { for (const i in this.Form.controls) { if (this.Form.controls.hasOwnProperty(i)) { this.Form.controls[i].markAsDirty(); this.Form.controls[i].updateValueAndValidity(); } } // 等待所有异步校验完成,获取最终校验状态 this.Form.statusChanges .pipe( // 过滤pending状态,只拿最终校验结果 filter(status => status !== 'PENDING'), // 只取一次结果自动销毁订阅,避免内存泄漏 take(1) ) .subscribe(status => { if (status !== 'VALID') { this.notification.createNotification('error', 'Validation error!', 'Please correct the form!') return; } // 此处写表单提交逻辑 }) }
方案2:提交时跳过异步校验
如果你的业务场景允许提交时只校验同步规则,可以直接在调用updateValueAndValidity时指定忽略异步校验,无需修改其他逻辑,适配Angular 12及以上版本:
save(): void { for (const i in this.Form.controls) { if (this.Form.controls.hasOwnProperty(i)) { this.Form.controls[i].markAsDirty(); // 新增配置项,忽略异步校验执行 this.Form.controls[i].updateValueAndValidity({asyncValidators: 'ignore'}); } } // 此时只会跑同步校验,不会出现pending状态,可直接判断valid if (!this.Form.valid) return this.notification.createNotification('error', 'Validation error!', 'Please correct the form!') // 此处写表单提交逻辑 }
内容的提问来源于stack exchange,提问作者flowstacker
相关产品推荐
相关产品推荐

