2016-04-06 13 views
5

私はAngular2でフォームの検証を完了しようとしています。angular2非同期フォームの検証

私は、非同期呼び出しによって、ユーザー名が既に取得され、データベースで使用されているかどうかを調べようとしています。ここで

は、これまでの私のコードです:

フォームコンポーネント:

import {Component, OnInit} from 'angular2/core'; 
import {FORM_PROVIDERS, Control, ControlGroup, FormBuilder, Validators} from 'angular2/common'; 
import {Http, Headers, RequestOptions} from 'angular2/http'; 
import {ROUTER_DIRECTIVES, Router, RouteParams} from 'angular2/router'; 
import {ControlMessages} from './control.messages'; 
import {ValidationService} from './validation.service'; 

@Component({ 
    selector: 'account-form', 
    templateUrl: './app/account/account.form.component.html', 
    providers: [ROUTER_DIRECTIVES, CaseDataService], 
    directives: [ControlMessages] 
}) 

accountForm: ControlGroup; 

constructor(private _accountService: AccountDataService, 
    private _formBuilder: FormBuilder, private _router: Router, private _params?: RouteParams) { 
    this.model = this._accountService.getUser(); 

    this.accountForm = this._formBuilder.group({ 
     'firstName': ['', Validators.required], 
     'lastName': ['', Validators.required], 
     'userName': ['', Validators.compose([ValidationService.userNameValidator, ValidationService.userNameIsTaken])], 

.... 
} 

検証サービス:

export class ValidationService { 


static getValidatorErrorMessage(code: string) { 
    let config = { 
     'required': 'Required', 
     'invalidEmailAddress': 'Invalid email address', 
     'invalidPassword': 'Invalid password. Password must be at least 6 characters long, and contain a number.', 
     'mismatchedPasswords': 'Passwords do not match.', 
     'startsWithNumber': 'Username cannot start with a number.' 
    }; 
    return config[code]; 
} 

static userNameValidator(control, service, Headers) { 
    // Username cannot start with a number 
    if (!control.value.match(/^(?:[0-9])/)) { 
     return null; 
    } else { 
     return { 'startsWithNumber': true }; 
    } 
} 
    // NEEDS TO BE AN ASYNC CALL TO DATABASE to check if userName exists. 
// COULD userNameIsTaken be combined with userNameValidator?? 

static userNameIsTaken(control: Control) { 
    return new Promise(resolve => { 
     let headers = new Headers(); 
     headers.append('Content-Type', 'application/json') 

     // needs to call api route - _http will be my data service. How to include that? 

     this._http.get('ROUTE GOES HERE', { headers: headers }) 
      .map(res => res.json()) 
      .subscribe(data => { 
       console.log(data); 
       if (data.userName == true) { 
        resolve({ taken: true }) 
       } 
       else { resolve({ taken: false }); } 
      }) 
    }); 
} 
} 

NEW CODE(×2を更新しました)。 ControlGroupは未定義に戻ります。

this.form = this.accountForm; 
    this.accountForm = this._formBuilder.group({ 
     'firstName': ['', Validators.required], 
     'lastName': ['', Validators.required], 
     'userName': ['', Validators.compose([Validators.required, this.accountValidationService.userNameValidator]), this.userNameIsTaken(this.form, 'userName')], 
     'email': ['', Validators.compose([Validators.required, this.accountValidationService.emailValidator])], 
     'password': ['', Validators.compose([Validators.required, this.accountValidationService.passwordValidator])], 
     'confirm': ['', Validators.required] 
    });   
}; 

userNameIsTaken(group: any, userName: string) { 
    return new Promise(resolve => { 

     this._accountService.read('/username/' + group.controls[userName].value) 
      .subscribe(data => { 
       data = data 
       if (data) { 
        resolve({ taken: true }) 
       } else { 
        resolve(null); 
       } 
      }); 
    }) 
}; 

HTML:Validators.compose方法と

'userName': ['', ValidationService.userNameValidator, 
     ValidationService.userNameIsTaken], 

そしてません:

<div class="input-group"> 
    <span class="input-group-label">Username</span> 
    <input class="input-group-field" type="text" required [(ngModel)]="model.userName" ngControl="userName" #userName="ngForm"> 
    <control-messages control="userName"></control-messages> 
    <div *ngIf="taken">Username is already in use.</div> 
</div> 

答えて

5

あなたの非同期バリデータをこのように定義する必要があります。 {:偽取ら}

if (data.userName == true) { 
    resolve({ taken: true }) 
} else { 
    resolve(null); 
} 

を参照してくださいユーザ名が代わりに `を撮影されていない場合にさらに

'<field-name>': [ '', syncValidators, asyncValidators ] 

あなたはnullを解決する必要があります。実際のところ、ここでのパラメータはに対応するものです詳細については、この記事(セクション "フィールドの非同期検証"):

編集

多分私の答えは十分ではありません。あなたはまだValidators.composeを使用する必要がありますが、いくつかの同期バリデータを持っているときにのみ:

this.accountForm = this._formBuilder.group({ 
    'firstName': ['', Validators.required], 
    'lastName': ['', Validators.required], 
    'userName': ['', Validators.compose([ 
      Validators.required, 
      this.accountValidationService.userNameValidator 
      ], this.userNameIsTaken], 
    'email': ['', Validators.compose([ 
      Validators.required, 
      this.accountValidationService.emailValidator 
      ]], 
    'password': ['', Validators.compose([ 
      Validators.required, 
      this.accountValidationService.passwordValidator 
      ]], 
    'confirm': ['', Validators.required] 
    });   
}; 

EDIT1

あなたがFormBuilderクラスを使用してコントロールを定義するのであなたがngFormControl代わりのngControl 1を活用する必要があります。

<div class="input-group"> 
    <span class="input-group-label">Username</span> 
    <input class="input-group-field" type="text" required [(ngModel)]="model.userName" [ngControl]="accountForm.controls.userName" > 
    <control-messages [control]="accountForm.controls.userName"></control-messages> 
    <div *ngIf="accountForm.controls.userName.errors && accountForm.controls.userName.errors.taken">Username is already in use.</div> 
</div> 

詳細はこちらの記事を参照してください。

+0

こんにちはティエリは - ありがとうございます。私は上記のコードを追加しましたが、それでも起動することはできません。 : – wjfieseler

+0

あなたのコードにはまだ問題があります。私は自分の答えを更新しました... –

+0

進歩しています。ここに更新されたコードがありますが、私はコントロールグループにアクセスできません。 – wjfieseler

関連する問題