2016-04-06 3 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 }); } 
      }) 
    }); 
} 
} 

НОВЫЙ КОД (ОБНОВЛЕНО x2). 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:

<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

Вы должны определить ваш ASync валидатор так:

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

И не с помощью метода Validators.compose. В самом деле, вот что параметры соответствуют:

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

Кроме того, вы должны решить с нулем, если имя пользователя не берется вместо `{сделано ложное}

if (data.userName == true) { 
    resolve({ taken: true }) 
} else { 
    resolve(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

Вы должны использовать в ngFormControl вместо ngControl один, потому что вы определяете элементы управления с помощью FormBuilder класса.

<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

Смежные вопросы