使用 ngrx 进行异步验证
AsyncValidation with ngrx
我有以下表格,我想根据 ngrx 存储中的值进行验证
this.form = new FormGroup({
serviceNr: new FormControl('', {
validators: [Validators.required],
}, [this.doubleServiceNrAsyncValidator()]),
...
});
我确保我的验证器是有限的,根据 Angular 文档
ngOnDestroy(): void {
this.isDestroyed.next(true);
this.isDestroyed.complete();
}
在我的模板中
<mat-error *ngIf="form.get('serviceNr').hasError('existingNr')">
{{ 'GENERAL.ALERTS.ERROR.RESOURCE_ALREADY_EXIST' | translate : { number: this.form.get('serviceNr').value } }}
</mat-error>
我的验证函数如下所示:
doubleServiceNrAsyncValidator = () => (_) => this.store.pipe(select(selectError)).pipe(
takeUntil(this.isDestroyed),
map(err => {
if (err?.errorCode === ErrorCodeEnum.RESOURCE_ALREADY_EXIST) {
return { existingNr: true };
}
if (!!err) {
return { unknown: true };
}
return null;
}),
)
正在调用异步验证器,它 returns { existingNr: true }
没问题。但是该字段未被标记为 invalid
这种行为是由于您的
this.store.pipe(select(selectError))
observable 永远不会完成,这导致与验证关联的表单控件处于 PENDING
状态。当 formControl
处于这种状态时,不会对其应用任何更改 valid
属性.
快速解决方法是在验证器中使用 take(1)
或 first()
,如下所示:
doubleServiceNrAsyncValidator = () => (_) => this.store.pipe(select(selectError)).pipe(
first(),
map(err => {
if (err?.errorCode === ErrorCodeEnum.RESOURCE_ALREADY_EXIST) {
return { existingNr: true };
}
if (!!err) {
return { unknown: true };
}
return null;
}),
first
运算符将完成源流,这将导致 formControl 将所有必要的更改应用到 valid
字段
在下面的 CodeSandbox 中,我创建了一个并排示例,您和将来的任何人都可能会发现它很有用,因为这是您通常不会在文档中找到的情况之一:D
我有以下表格,我想根据 ngrx 存储中的值进行验证
this.form = new FormGroup({
serviceNr: new FormControl('', {
validators: [Validators.required],
}, [this.doubleServiceNrAsyncValidator()]),
...
});
我确保我的验证器是有限的,根据 Angular 文档
ngOnDestroy(): void {
this.isDestroyed.next(true);
this.isDestroyed.complete();
}
在我的模板中
<mat-error *ngIf="form.get('serviceNr').hasError('existingNr')">
{{ 'GENERAL.ALERTS.ERROR.RESOURCE_ALREADY_EXIST' | translate : { number: this.form.get('serviceNr').value } }}
</mat-error>
我的验证函数如下所示:
doubleServiceNrAsyncValidator = () => (_) => this.store.pipe(select(selectError)).pipe(
takeUntil(this.isDestroyed),
map(err => {
if (err?.errorCode === ErrorCodeEnum.RESOURCE_ALREADY_EXIST) {
return { existingNr: true };
}
if (!!err) {
return { unknown: true };
}
return null;
}),
)
正在调用异步验证器,它 returns { existingNr: true }
没问题。但是该字段未被标记为 invalid
这种行为是由于您的
this.store.pipe(select(selectError))
observable 永远不会完成,这导致与验证关联的表单控件处于 PENDING
状态。当 formControl
处于这种状态时,不会对其应用任何更改 valid
属性.
快速解决方法是在验证器中使用 take(1)
或 first()
,如下所示:
doubleServiceNrAsyncValidator = () => (_) => this.store.pipe(select(selectError)).pipe(
first(),
map(err => {
if (err?.errorCode === ErrorCodeEnum.RESOURCE_ALREADY_EXIST) {
return { existingNr: true };
}
if (!!err) {
return { unknown: true };
}
return null;
}),
first
运算符将完成源流,这将导致 formControl 将所有必要的更改应用到 valid
字段
在下面的 CodeSandbox 中,我创建了一个并排示例,您和将来的任何人都可能会发现它很有用,因为这是您通常不会在文档中找到的情况之一:D