2016-03-26 3 views
11

У меня проблема с определением асинхронного валидатора в форме с шаблоном.Угловой шаблонный валидатор с привязкой к шаблону

В настоящее время у меня есть этот вход:

<input type="text" ngControl="email" [(ngModel)]="model.applicant.contact.email" #email="ngForm" required asyncEmailValidator> 

с селектором валидатора asyncEmailValidator, которая указывает на этот класс:

import {provide} from "angular2/core"; 
import {Directive} from "angular2/core"; 
import {NG_VALIDATORS} from "angular2/common"; 
import {Validator} from "angular2/common"; 
import {Control} from "angular2/common"; 
import {AccountService} from "../services/account.service"; 

@Directive({ 
selector: '[asyncEmailValidator]', 
providers: [provide(NG_VALIDATORS, {useExisting: EmailValidator, multi: true}), AccountService] 
}) 

export class EmailValidator implements Validator { 
//https://angular.io/docs/ts/latest/api/common/Validator-interface.html 


constructor(private accountService:AccountService) { 
} 

validate(c:Control):{[key: string]: any} { 
    let EMAIL_REGEXP = /^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i; 

    if (!EMAIL_REGEXP.test(c.value)) { 
     return {validateEmail: {valid: false}}; 
    } 

    return null; 

    /*return new Promise(resolve => 
     this.accountService.getUserNames(c.value).subscribe(res => { 
      if (res == true) { 
       resolve(null); 
      } 
      else { 
       resolve({validateEmailTaken: {valid: false}}); 
      } 
     }));*/ 
} 

}

Email регулярное выражение часть работает, как ожидалось, и форма успешно проверяется, если регулярное выражение совпадает. Но после этого я хочу проверить, не используется ли электронная почта, поэтому я создаю обещание для своей учетной записи. Но это не работает вообще, и форма постоянно находится в состоянии отказа.

Я прочитал о модели инициативе форм и использование FormBuilder, как показано ниже:

constructor(builder: FormBuilder) { 
this.email = new Control('', 
    Validators.compose([Validators.required, CustomValidators.emailFormat]), CustomValidators.duplicated 
); 
} 

Которые асинхронные валидаторы определены в третьем параметре Control() Но это не мой случай, потому что им с помощью diffrent подхода ,

Итак, мой вопрос: возможно ли создание асинхронного валидатора с использованием форм-шаблонов?

ответ

13

Вы могли бы попытаться зарегистрировать поставщик вашего асинхронного валидатора с ключом NG_ASYNC_VALIDATORS и не NG_VALIDATORS один (только для синхронных валидаторов):

@Directive({ 
    selector: '[asyncEmailValidator]', 
    providers: [ 
    provide(NG_ASYNC_VALIDATORS, { // <------------ 
     useExisting: EmailValidator, multi: true 
    }), 
    AccountService 
    ] 
}) 
export class EmailValidator implements Validator { 
    constructor(private accountService:AccountService) { 
    } 

    validate(c:Control) { 
    return new Promise(resolve => 
     this.accountService.getUserNames(c.value).subscribe(res => { 
     if (res == true) { 
      resolve(null); 
     } 
     else { 
      resolve({validateEmailTaken: {valid: false}}); 
     } 
    })); 
    } 
} 

Посмотреть этот документ на angular.io сайта:

+0

Спасибо! Это именно то, что я хотел. Btw. Возможно ли совместить асинхронную часть валидатора (обещание) с частью noasync (только регулярное выражение) в одном классе валидатора таким образом, что часть async будет запущена только в том случае, если регулярное выражение в порядке или мне нужно обоим отдельно? – Marduk

+0

Да, но вы можете в обоих случаях решить обетование. Последний может быть разрешен, даже если обработка не является асинхронной ... –

+0

Хорошо, я попробую. Еще раз спасибо. – Marduk

1

стоит отметить, что синтаксис изменился с го ru, теперь я пользуюсь угловым 4, и здесь ниже перепишите:

import { Directive, forwardRef } from '@angular/core'; 
import { AbstractControl, Validator, NG_ASYNC_VALIDATORS } from '@angular/forms'; 
import { AccountService } from 'account.service'; 

@Directive({ 
    selector: '[asyncEmailValidator]', 
    providers: [ 
     { 
      provide: NG_ASYNC_VALIDATORS, 
      useExisting: forwardRef(() => EmailValidatorDirective), multi: true 
     }, 
    ] 
}) 
export class EmailValidatorDirective implements Validator { 
    constructor(private _accountService: AccountService) { 
    } 

    validate(c: AbstractControl) { 
     return new Promise(resolve => 
      this._accountService.isEmailExists(c.value).subscribe(res => { 
       if (res == true) { 
        resolve({ validateEmailTaken: { valid: false } }); 
       } 
       else { 
        resolve(null); 
       } 
      })); 
    } 
} 
Смежные вопросы