次の場合、customerNameValidatorに何を返す必要がありますか
非同期検証が失敗/成功し、「customerName」FormControlが無効ですか?
this.customerForm = this.formBuilder.group({
customerName:
[this.newCustomerName, [Validators.minLength(2), Validators.required],[this.customerNameValidator.bind(this)]]
});
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).subscribe(response =>
{
if(response == true)
{
alert("true");
}
else
{
alert("false");
}
});
}
サブスクライブするのではなく、オブザーバブルをマップして、ストリームから読み取るのではなく、戻ってくるストリームの結果を変更する必要があります。
customerNameValidator(c: AbstractControl)
{
return this.service.customerExists(c.value,this.companyId).map(response =>
{
if(response == true)
{
return { customerExists: true };
}
else
{
return;
}
});
}
Trueの値を持つオブジェクトを返すことは、observableを返す方法です。非同期バリデーターのいくつかの重要な手順を見逃しているかもしれませんが、すべてのコードを提供しているわけではないため、言うのは難しいです。 この記事をチェックしてみてください または この記事 詳細については。
angular 6.1.1。にAsyncValidatorFnを使用してリアクティブフォームを実装しました。私の学習の一部を共有したいと思います。
angularは、内部同期バリデーターの場合とは異なり、AsyncValidatorFnのフォームコントロールを(自動的に)更新しないことがわかりました。
したがって、「AsyncValidatorFn」インターフェース仕様に従って、の実装でフォームコントロールを「手動で」更新する必要があります。
(c: AbstractControl): Promise<ValidationErrors | null> | Observable<ValidationErrors | null>;
次に、html要素の制御状態を確認します
私が実装したのは、ユーザーのサインアッププロセスで非常に一般的に見られるユーザー名の存在チェックです。
以下はコードの抜粋です。
フォームコントロール
// Supports alphabets and numbers no special characters except underscore('_') and dash('-') min 3 and max 20 characters.
this.userName = new FormControl('', Validators.compose([Validators.required, Validators.pattern('^[A-Za-z0-9_-]{3,20}$')]),Validators.composeAsync([this.checkUser()]));
カスタム非同期バリデーターとヘルパー関数
checkUser (): AsyncValidatorFn{
return (c: AbstractControl): Observable<ValidationErrors> => {
return c
.valueChanges
.debounceTime(400)
.mergeMap(value => this.gabriel.filter({'userName':value}))
.map(stat => this.mapErr(c, stat));
}
}
private mapErr(c: AbstractControl, res: any): ValidationErrors{
let err: ValidationErrors;
switch (res['state']){
case 0:
err = null;
break;
case -100:
err = {'existed': true};
break;
case -1:
default:
err = {'failed': true};
}
c.setErrors(err);
return err;
}
コントロールをパラメーターとして「mapErr」関数に入力し、「c.setErrors(err);」でコントロールを設定することに注意してください。
「returnerr;」ステートメントは、「AsyncValidatorFn」インターフェース仕様に従って「ValidationErrors」を返します。
「gabriel.filter()」は、抽出されたユーザー名でバックエンドを照会します。 「ok」、「duplicated」、「operationfailed」の場合はそれぞれ0、-100、-1を返します。
filter(json): Observable<{}>{
let body = JSON.stringify(json);
let headers = new Headers({'Content-Type': 'application/json'});
let options = new RequestOptions({ headers: headers });
return this.http.post(Cons.filter, body, options).timeout(10000).map((res:Response) => res.json());
}
htmlファイルのコントロールチェック
<form [formGroup]="sf" (ngSubmit)="signin()">
<ion-item>
<ion-label>UserName</ion-label>
<ion-input type="text" formControlName="userName" [class.invalid]="userName.dirty&&userName.invalid&&userName.errors!=null" ></ion-input>
</ion-item>
<p *ngIf="userName.dirty && userName.hasError('existed')">
Username already existed
</p>
<p *ngIf="userName.dirty && userName.hasError('failed')">
can not check validity of Username
</p>
また、1つのフォームコントロールで同期バリデーターが満たされるまで、非同期バリデーターがトリガーされないこともわかりました。
私の場合、組み込みのValidators.patternを使用して、最小長3を定義しました(上記のユーザー名formControl定義を参照)
入力の長さが3より短い限り、カスタム非同期バリデーターはトリガーされません。