我想分两步验证一个名为“name”的字段,首先是同步,然后是异步检查“name”是否在表单提交之后使用。
app.component.html
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
<input type="text" formControlName="name"/>
<div *ngIf="name?.invalid && (name?.dirty || name?.touched)">
<div *ngIf="name?.errors?.maxlength">
Max error
</div>
</div>
<div *ngIf="myForm?.errors?.hasTaken">
This name is already taken
</div>
<button type="submit">Go</button>
</form>
app.component.ts
import { Component, Injectable } from '@angular/core';
import {AbstractControl, AsyncValidator, FormControl, FormGroup, ValidationErrors, Validators} from '@angular/forms';
import {combineLatest, from, Observable, of} from 'rxjs';
import {map} from 'rxjs/operators';
// simulation of validation
function UniqueNameValidator(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
let promise = new Promise<ValidationErrors | null>((resolve, reject) => {
const nameControl = control.get('name');
if (nameControl?.value === 'ok') {
setTimeout(() => resolve(null), 1000)
} else {
setTimeout(() => resolve({
hasTaken: true
}), 1000)
}
})
return promise;
}
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
export class AppComponent {
myForm = new FormGroup({
name: new FormControl('', {
validators: Validators.maxLength(10),
})
}, {
asyncValidators: UniqueNameValidator,
updateOn: 'submit'
});
onSubmit() {
console.log(this.myForm)
}
get name() { return this.myForm.get('name'); }
}
但是我得到的是调用异步验证,即使我在输入中没有输入任何内容并且没有按下按钮。
如何修复此行为并同步验证,然后在提交后使用异步验证?
答案 0 :(得分:0)
在调用您的承诺之前检查输入字符串的长度
function UniqueNameValidator(control: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null> {
if(nameControl?.value.length < 10){
return Promise.resolve()
}
let promise = new Promise<ValidationErrors | null>((resolve, reject) => {
const nameControl = control.get('name');
if (nameControl?.value === 'ok') {
setTimeout(() => resolve(null), 1000)
} else {
setTimeout(() => resolve({
hasTaken: true
}), 1000)
}
})
return promise;
}
看起来您正在调用表单上的验证器而不是输入。我更喜欢[form builder][1]
,但是...
// with FB injected as fb
const form = this.fb.group({name:[null, [Validators.max(10)], [UniqueNameValidator] ]})
作为奖励,您可以将最小长度值传递给验证器。您可以通过将 UniqueNameValidator
包装在一个函数中来做到这一点。您可以将其称为 UniqueNameValidatorWrapper(10)