Consumir webservices con angular
Consumir webservices con angular es algo que siempre vamos a usar, aunque con javascript nativo usamos xhr o fetch, angular nos facilita la vida para consumir webservices con la librería httpCliente.
Crear webservices de prueba
No hay que tener conocimientos previos para hacer esta prueba solo conocer la estructura json, para esto vamos a usar un programa en nodejs que nos emula una base de datos al puro estilo de mongoDB.
El proyecto se llama JSON-SERVER y se usa de la siguiente manera.
Vamos a instalarlo en nuestro nodejs:
npm install -g json-server
una vez instalado vamos a crear un archivo de texto plano que se llame db.json, ahora crearemos nuestra estructura, usaremos la estructura de ejemplo que nos da:
{ "posts": [ { "id": 1, "title": "json-server", "author": "typicode" } ], "comments": [ { "id": 1, "body": "some comment", "postId": 1 } ], "profile": { "name": "typicode" } }
Vamos a iniciar nuestro servicio
json-server --watch db.json
vamos a ver algo asi en nuestra consola
podemos ver como funciona muy sencillo, si quieren probar las peticiones les recomiendo postman, solo les recomiendo usar la cabecera de application/json para que no falle su consulta.
Consumir webservices con angular
Bueno para este momento debemos tener en mente lo siguiente
- crear proyecto
- crear componentes
- Usar formularios
- entender un poco de RXJS
Vamos a crear nuestro formulario donde vamos a consumir webservices con angular
<section> <div class="mitad"> <div class="peticiones"> <h2>Peticion Post</h2> <form> <input type="text" placeholder="Titulo" /> <input type="text" placeholder="Autor" /> <button>Post</button> </form> </div> <div class="peticiones"> <h2>Peticion Get (todos)</h2> <button>Get</button> </div> <div class="peticiones"> <h2>Peticion Put</h2> <form> <input type="number" placeholder="id" /> <input type="text" placeholder="Titulo" /> <input type="text" placeholder="Autor" /> <button>put</button> </form> </div> </div> <div class="mitad result"> </div> </section>
css
.peticiones { margin: 20px 10px; border: 1px dotted black; padding: 50px; } .mitad { width: 40%; align-items: flex-start; flex-direction: row; justify-content: center; } section { width: 100%; display: flex; justify-content: space-around; } .result { align-items: stretch; border: 1px solid black; }
Vamos a crear un servicio
Servicios para consumir webservices con angular
La idea principal de angular es que todo sea asíncrono, es decir que nada detenga el hilo principal y que se esté trabajando en segundo plano, así que nace los servicios.
Los servicios se encarga de procesar información, convertirlas si es necesaria y entregar a nuestra vista de la forma más sencilla y sin hacer un procesado extra, services se posiciona de esta manera.
Services no solo se usa para el consumir webservices con angular, también lo puedes usar para alguna otra tarea que necesite procesar información de grande volúmenes.
Crear Services con angular cli
ng g service 'nombredeservicio' o ng g service 'nombredecarpeta/nombreservices'
con esto estamos creando nuestro archivo services que va a consumir un webservices con angular, vamos a importar nuestras librerias correspondientes, lo primero que vamos a ver es la librería Injectable, esta hace que la información se coloque en componentes en cierta parte.
El inyector lo instancia y lo guarda en un contenedor, busca primero en este contenedor cada vez que inyectamos algún servicio, por eso los servicios son singletons en el ámbito de su inyector.
un punto importante, es crear nuestros modelos de datos, esto para que hacer más fácil el envío y recibir información en nuestro web services.
Crear Modelos
Nuestros modelos simplemente son clases donde contiene nuestra información y el tipo de dato que va a recibir en este caso vamos usar los siguientes métodos de ApiRest:
- post
- get
- put
Como la peticion que estamos haciendo no va a ver variacion usare un modelo para el envio y otro para recibir informacion
//peticionEnvio.ts export class PeticionEnvio{ public title:String; public author:String; } //responseG.ts export class ResponseG{ public id:number; public title:String; public author:String; }
Importar y crear métodos en services
Services vamos a dividirlos en dos puntos, la primera seccion es todas las librerías que vamos a exportar y la segunda sección es toda la lógica que vamos a manejar, en este caso la lógica es simple, ya que nuestro servidor está regresando un json básico.
Inyectable
Injectable es parte de la magia que vamos a ver al consumir webservices con angular, osea es la parte donde vamos a ver las inserciones de datos.
Modelos
la importación de los modelos es la parte fundamental para no hacer un proceso de parseo de datos, así que la importancia es grande, en caso que nosotros no queramos hacer un modelo, o nuestra respuesta puede variar, usaremos la palabra reservada any en donde van los nombre de los métodos
postRespuesta(_body: PeticionEnvio): Observable<any> { return this.http.post<ResponseG>(this.url, _body); }
Observable
Este es un método muy importante, ya que para decirlo de manera muy simple, observable no bloqueara el hilo principal, simplemente estará pendiente cuando regrese algún dato que nos sirva.
HttpClient
La libreria estrella para consumir webservices con angular, la diferencia de las versiones anteriores de http, es que aqui mapea la información de manera automatica, es mas rapido y facil de usar, aqui esta la documentación directa de angular.
Este es el código de ejemplo:
//phttp.service.ts import { Injectable } from '@angular/core'; import {ResponseG} from './Model/responseG'; import {PeticionEnvio} from './Model/peticionEnvio'; import { Observable } from 'rxjs/Observable'; import {HttpClient} from '@angular/common/http'; @Injectable() export class PhttpService { private url: string = "http://localhost:3000/posts"; private ArrayG: Array<ResponseG>; constructor( private http: HttpClient) { } postRespuesta(_body: PeticionEnvio): Observable<ResponseG> { return this.http.post<ResponseG>(this.url, _body); } getRespuesta(): Observable<ResponseG[]> { return this.http.get<ResponseG[]>(this.url); } putRespuesta(_id: number, _body: PeticionEnvio): Observable<ResponseG> { let urlcom = this.url + "/" + _id; return this.http.put<ResponseG>(urlcom, _body); } }
En este casos vamos a crear un constructor y vamos a crear el valor http con httpclient, esto lo usaremos en cada una de nuestras funciones y sirve para hacer los llamados como post, put, get … etc.
funciones:
- postRespuesta – Petición post
- getRespuesta – Petición Get
- putRespuesta – Petición Put
voy a tomar la función post para explicar como se usa http.
Http
postRespuesta(_body: PeticionEnvio): Observable<ResponseG> {
}
lo primero que vamos a ver es la funcion en si, a diferencia de javascript no ponemos function nombre, simplemente ponemos el nombre la da función, enseguida le decimos que es de tipo Observable, que la respuesta esperada es un tipo ResponseG (nuestro modelo).
return this.http.post<ResponseG>(this.url, _body);
Esta funcion, al usar http, siempre nos va a regresar algo, asi que debemos retornar algun valor, en este caso this.http, es la variable que creamos en el constructor, post, es el método que vamos a usar y al igual que el observable, le decimos que nos va a regresar el servidor datos con la estructura de ResponseG.
Al final le pasamos la url del Api y el cuerpo del mensaje, también podemos agregar cabeceras de la siguiente manera:
//dentro del http.post( headers: HttpHeaders { [header: string]: string | string[]; }; ejemplo: return this.http.post(this.url, {headers: HttpHeaders: { 'Content-Type': 'application/json' }); o let headers = new HttpHeaders().set('Content-Type','application/x-www-form-urlencoded'); return this.http.post(this.url, {headers: headers});
y listo nuestro servidor está listo para hacer consultas.
Dar de alta nuestro services
una parte muy importante para consumir webservices con angular y httpClient, es dar de alta el servicio, estos archivos se deben colocar en nuestro archivo raiz app.module.ts.
de paso también vamos a agregar los Form
import { BrowserModule } from '@angular/platform-browser'; import { NgModule } from '@angular/core'; import { FormsModule } from '@angular/forms'; import {HttpClientModule} from '@angular/common/http'; import { AppComponent } from './app.component'; import {PhttpService} from './phttp.service'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserModule, FormsModule, HttpClientModule ], providers: [PhttpService], bootstrap: [AppComponent] }) export class AppModule { }
Aqui lo interesante, es que nuestros servicios debemos ponerlos en la parte que dice providers, en caso que no tenga esta propiedad deben agregarlo, esto se encarga en dar de alta los servicios y poder usarlos en cualquier componente, si ustedes prefieren que solo se vea en un solo lugar, pueden poner el providers en la configuración del componente.
Configurar la vista y el controlador
En este caso no explicare los form, pueden ver esta entrada, donde explico paso a paso
<section> <div class="mitad"> <div class="peticiones"> <h2>Peticion Post</h2> <form (ngSubmit)="onSubmit(1);" #peticionForm="ngForm"> <input type="text" placeholder="Titulo" #title name="title" [(ngModel)]="peticion.title" required /> <input type="text" placeholder="Autor" #author name="author" [(ngModel)]="peticion.author" required/> <button [disabled]="!peticionForm.form.valid">Post</button> </form> </div> <div class="peticiones"> <h2>Peticion Get (todos)</h2> <button (click)="getPeticion()">Get</button> </div> <div class="peticiones"> <h2>Peticion Put</h2> <form (ngSubmit)="onSubmit(2,idPut)" #putForm="ngForm"> <input type="number" placeholder="id" #idPut (change)="onchange($event)" name="idPut" min="1" required/><br/> <input type="text" placeholder="Titulo" #title2 name="title2" [(ngModel)]="peticionPut.title" required /> <input type="text" placeholder="Autor" #author2 name="author2" [(ngModel)]="peticionPut.author" required/> <button>put</button> </form> </div> </div> <div class="mitad result"> <h3>Resultado</h3> <div *ngFor="let resp of resultado "> <p>id: {{ resp.id }}</p> <p>Title: {{ resp.title }}</p> <p>Author: {{ resp.author }}</p> <hr> </div> </div> </section>
Configuración del archivo ts
Colocare todo el archivo que genere, recordemos que el onSubmit, es la función que dispara cuando le damos al boton de enviar en los form.
import { Component } from '@angular/core'; import {PeticionEnvio} from './Model/peticionEnvio'; import {ResponseG} from './Model/responseG'; import {PhttpService} from './phttp.service'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.css'] }) export class AppComponent { peticion = new PeticionEnvio(); peticionPut = new PeticionEnvio(); resultado: Array<ResponseG>; id: number = 1; constructor(private phttp: PhttpService) { } onSubmit(tipo: number) { switch ( tipo ) { case 1: this.postSentServices(this.peticion); break; case 2: if(this.peticionPut.author == null && this.peticionPut.title == null){ alert("llene todo los campos de put"); }else{ this.putSentServices(this.peticionPut, this.id); } break; } } onchange($event) { this.id = $event.target.value; } getPeticion() { this.phttp.getRespuesta().subscribe( data => { this.resultado = data; }, err => { console.log(err); } ); } postSentServices(body: PeticionEnvio) { this.phttp.postRespuesta(body).subscribe( data => { this.resultado = []; this.resultado.push(data); }, err => {} ); } putSentServices(body: PeticionEnvio, id: number) { this.phttp.putRespuesta(id, body).subscribe( data => { this.resultado = []; this.resultado.push(data); }, err => {} ); } }
La función onchange, me sirve para capturar el valor específico de un solo input, en este caso es el la parte del put
<input type=»number»placeholder=»id» #idPut (change)=»onchange($event)»name=»idPut»min=»1″required/><br/>
Enviar nuestro valor al services
es momento de consumir webservices!!, asi que en nuestro constructor llamaremos a nuestro services, y crearemos la funcion donde llenaremos lo que necesitamos en ese services
postSentServices(body: PeticionEnvio) { this.phttp.postRespuesta(body).subscribe( data => { this.resultado = []; this.resultado.push(data); }, err => {} ); }
con esta pequeña llamada, le decimos que data tendra la informacion de la respuesta del servidor, esta respuesta ya esta parciada con nuestros modelos y podemos consultarlos.
recordemos que para ver nuestros resultados en el html, en tiempo real, hay que colocar el nombre de la variable creada en nuestro controlador (.ts) entre llaves por ejemplo
<p>{{resultado}}</p>
Con esto podemos hacer consultas a webservices y realizar acciones mediante las respuestas, la librería httpClient es muy fácil de usar, y en pocos pasos ya estamos consumir webservices con angular.
Dejaré el enlace del proyecto para que lo bajen y puedan probar
[…] En esta entrada explico un poco más como funciona los servicios y también como consumir un webservices. […]