Implementa validaciones asíncronas en angular de manera simple con este sencillo tutorial.
December 24, 2020 , 3 min read
Share with:Crear validaciones asincronas customisadas para los formularios reactivos en angular.
Las validaciones asíncronas son aquellas en las cuales debemos hacer una solicitud externa y de acuerdo a ello validar los datos, por ejemplo para validar un nombre de usuario (usersname), primero debemos hacer una solicitud a nuestra base de datos y comprobar que el nombre de usuario está disponible, esto es una validación asíncrona.
Normalmente se realizar la solicitud a un backend real pero para este ejemplo dentro del proyeto de angular en el path /assets/user.json. Se colocara los datos de prueba a ser validadados como si fuera la respuesta que devolveria un backend.
user.json
[
{
"name": "Paul",
"email": "paul@example.com"
},
{
"name": "Ringo",
"email": "ringo@example.com"
},
{
"name": "John",
"email": "john@example.com"
},
{
"name": "George",
"email": "george@example.com"
}
]
Se creara un servicio con el método checkEmail que active una llamda GET http a nuestro archivo JSON. Se utlizara el operador delay de la librerai RxJS's para simular la latencia entre la comunicación de backend y frontend.
app.service.ts
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { map, delay, mergeMap, filter } from "rxjs/operators";
import { Observable } from "rxjs";
@Injectable()
export class AppService {
constructor(private http: Http) {}
checkEmail(email: string) {
console.log(
"valor",
this.http.get("assets/users.json").pipe(
map(res => res.json()),
map(users => users.filter(user => user.email === email))
)
);
return this.http.get("assets/users.json").pipe(
map(res => res.json()),
map(users => users.filter(user => user.email === email))
);
}
}
Observe cómo filtramos para los usuarios que tienen el mismo correo electrónico que el proporcionado al método. Luego, mapeamos los resultados nuevamente y probamos para asegurarnos de que obtenemos un objeto vacío.
En este componente se inicializa nuestro reactive froms y nuestra validacion asincrona validarEmail Se observa como en nuestro FormBuilder.group. Como ven primero va el valor por defecto, luego declaramos el conjunto de la validaciones sincronas y luego el conjunto de validaciones asíncronas.
app.component.ts
import { Component, OnInit } from "@angular/core";
import {
FormBuilder,
FormGroup,
Validators,
AbstractControl
} from "@angular/forms";
import { AppService } from "./app.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent implements OnInit {
myForm: FormGroup;
constructor(private fb: FormBuilder, private signupService: AppService) {}
ngOnInit() {
this.myForm = this.fb.group({
name: ["", Validators.required],
email: [
"",
[Validators.required, Validators.email],
this.validarEmail.bind(this)
]
});
}
validarEmail(control: AbstractControl) {
return this.signupService.checkEmail(control.value).subscribe(res => {
return res ? null : { emailTaken: true };
});
}
}
Nuestro validador es muy similar a un validador personalizado típico. Aquí hemos definido nuestro validador en la clase de componente directamente en lugar de un archivo separado. Esto facilita el acceso a nuestra instancia de servicio inyectado. Observe también cómo necesitamos vincular this valor para asegurarnos de que apunta a la clase de componente.
app.component.html
<div style="text-align:center">
<form [formGroup]="myForm">
<input type="text" formControlName="name">
<input type="email" formControlName="email">
<div *ngIf="myForm.get('email').status === 'PENDING'">
Checking...
</div>
<div *ngIf="myForm.get('email').status === 'VALID'">
Email valido
</div>
<div *ngIf="myForm.get('email').errors ">
Este email no es correcto
</div>
</form>
</div>