Angular2 шаблонный асинхронный валидатор
У меня проблема с определением асинхронного валидатора в форме с шаблоном.
В настоящее время у меня есть этот вход:
<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}});
}
}));*/
}
}
Элемент регулярного выражения электронной почты работает как ожидалось, и форма успешно проверяется, если регулярное выражение соответствует. Но после этого я хочу проверить, не используется ли электронная почта, поэтому я создаю обещание для своей учетной записи. Но это не работает вообще, и форма постоянно находится в состоянии отказа.
Я читал о формах, управляемых моделью, и используя FormBuilder, как показано ниже:
constructor(builder: FormBuilder) {
this.email = new Control('',
Validators.compose([Validators.required, CustomValidators.emailFormat]), CustomValidators.duplicated
);
}
Какие имеют асинхронные валидаторы, определенные в третьем параметре Control(). Но это не мой случай, потому что im использует различный подход.
Итак, мой вопрос: возможно ли создать асинхронный валидатор с использованием форм, управляемых шаблонами?
Ответы
Ответ 1
Вы можете попытаться зарегистрировать поставщика вашего асинхронного валидатора с помощью клавиши 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:
Ответ 2
стоит отметить, что синтаксис изменился с тех пор, теперь я использую angular 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);
}
}));
}
}