angular - angular2 async form validation -


i trying accomplish piece of form validation angular2.

i trying find out, via asynchronous call, if username has been taken , used in database.

here code far:

form component:

import {component, oninit} 'angular2/core'; import {form_providers, control, controlgroup, formbuilder, validators} 'angular2/common'; import {http, headers, requestoptions} 'angular2/http'; import {router_directives, router, routeparams} 'angular2/router'; import {controlmessages} './control.messages'; import {validationservice} './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])],  .... } 

validation service:

export class validationservice {   static getvalidatorerrormessage(code: string) {     let config = {         'required': 'required',         'invalidemailaddress': 'invalid email address',         'invalidpassword': 'invalid password. password must @ least 6 characters long, , contain number.',         'mismatchedpasswords': 'passwords not match.',         'startswithnumber': 'username cannot start number.'     };     return config[code]; }  static usernamevalidator(control, service, headers) {     // username cannot start number     if (!control.value.match(/^(?:[0-9])/)) {         return null;     } else {         return { 'startswithnumber': true };     } }   // needs async call database check if username exists.  // usernameistaken combined usernamevalidator??  static usernameistaken(control: control) {     return new promise(resolve => {         let headers = new headers();         headers.append('content-type', 'application/json')          // needs call api route - _http data service. how 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 (updated x2). controlgroup returning undefined.

    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:

<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 in use.</div> </div> 

you should define async validator way:

'username': ['', validationservice.usernamevalidator,         validationservice.usernameistaken], 

and not validators.compose method. matter of fact, here parameters correspond to:

'<field-name>': [ '', syncvalidators, asyncvalidators ] 

moreover should resolve null when user name isn't taken instead of `{taken: false}

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

see article more details (section "asynchronous validation fields"):

edit

perhaps answer isn't clear enough. still need use validators.compose when have several synchronous validators:

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

you need leverage ngformcontrol instead of ngcontrol 1 because define controls using formbuilder class.

<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 in use.</div> </div> 

see article more details:


Comments