web-dev-qa-db-ja.com

オブザーバブルを使用するときにangular 2非同期バリデーターで返すもの

次の場合、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");
        }
   });
}
6
Elisabeth

サブスクライブするのではなく、オブザーバブルをマップして、ストリームから読み取るのではなく、戻ってくるストリームの結果を変更する必要があります。

customerNameValidator(c: AbstractControl)
{
   return this.service.customerExists(c.value,this.companyId).map(response =>
   {
        if(response == true)
        {
            return { customerExists: true };
        }
        else
        {
            return;
        }
   });
}

Trueの値を持つオブジェクトを返すことは、observableを返す方法です。非同期バリデーターのいくつかの重要な手順を見逃しているかもしれませんが、すべてのコードを提供しているわけではないため、言うのは難しいです。 この記事をチェックしてみてください または この記事 詳細については。

10
Adam

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より短い限り、カスタム非同期バリデーターはトリガーされません。

8
George Wang