validation - formulario - validar campos con angular 2
Validador asíncrono controlado por plantilla Angular2 (2)
Puede tratar de registrar el proveedor de su validador asíncrono con la clave NG_ASYNC_VALIDATORS
y no con NG_VALIDATORS
(solo para validadores síncronos):
@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}});
}
}));
}
}
Ver este documento en el sitio web angular.io:
Tengo un problema con la definición de validador asincrónico en forma de plantilla.
Actualmente tengo esta entrada:
<input type="text" ngControl="email" [(ngModel)]="model.applicant.contact.email" #email="ngForm" required asyncEmailValidator>
con el selector del validador asyncEmailValidator que apunta a esta clase:
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}});
}
}));*/
}
}
La parte de expresión regular de correo electrónico está funcionando como se esperaba y la forma se está validando con éxito si la expresión regular se corresponde. Pero después de eso, quiero verificar si el correo electrónico no está en uso, por lo que estoy creando una promesa para mi accountService. Pero esto no funciona en absoluto y la forma está en estado fallido todo el tiempo.
He leído sobre formularios impulsados por modelos y el uso de FormBuilder como a continuación:
constructor(builder: FormBuilder) {
this.email = new Control('''',
Validators.compose([Validators.required, CustomValidators.emailFormat]), CustomValidators.duplicated
);
}
Que tienen validadores asíncronos definidos en el tercer parámetro de Control () Pero este no es mi caso porque estoy usando un enfoque diferente.
Entonces, mi pregunta es: ¿es posible crear un validador asíncrono utilizando formularios basados en plantillas?
Vale la pena señalar que la sintaxis ha cambiado desde entonces, ahora estoy usando angular 4, y aquí debajo una reescritura:
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);
}
}));
}
}