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
Post a Comment