Primero de los artículos dedicado a los servicios de Angular. Veremos qué son los servicios en el framework Javascript Angular, cómo crear services e inyectarlos en los componentes para acceder a ellos.
Hasta ahora en el Manual de Angular hemos hablado mucho de componentes, y también de módulos. Pero existen otros tipos de artefactos que podemos usar para organizar el código de nuestras aplicaciones de una manera más lógica y fácil de mantener.
En importancia a componentes y módulos le siguen los servicios. Con este artículo iniciamos su descripción. Los servicios, o "services" si lo prefieres en inglés, son una de las piezas fundamentales en el desarrollo de aplicaciones Angular. Veremos qué es un servicio y cómo dar nuestros primeros pasos en su creación y utilización en un proyecto.
Concepto de servicio en Angular
Si eres ya viejo conocido del desarrollo con Angular sabrás lo que es un servicio, pues es una parte importante dentro de la arquitectura de las aplicaciones con este framework. Pero si eres nuevo seguro que te vendrá bien tener una pequeña descripción de lo que es un servicio.
Básicamente hemos dicho anteriormente que el protagonista en las aplicaciones de Angular es el componente, que las aplicaciones se desarrollan en base a un árbol de componentes. Sin embargo, a medida que nuestros objetivos sean más y más complejos, lo normal es que el código de los componentes también vaya aumentando, implementando mucha lógica del modelo de negocio.
En principio esto no sería tan problemático, pero sabemos que la organización del código, manteniendo piezas pequeñas de responsabilidad reducida, es siempre muy positiva. Además, siempre llegará el momento en el que dos o más componentes tengan que acceder a los mismos datos y hacer operaciones similares con ellos, que podrían obligarnos a repetir código. Para solucionar estas situaciones tenemos a los servicios.
Básicamente un servicio es un proveedor de datos, que mantiene lógica de acceso a ellos y operativa relacionada con el negocio y las cosas que se hacen con los datos dentro de una aplicación. Los servicios serán consumidos por los componentes, que delegarán en ellos la responsabilidad de acceder a la información y la realización de operaciones con los datos.
Cómo crear un servicio
Tal como viene siendo costumbre en el desarrollo con Angular, nos apoyaremos en Angular CLI para la creación del esqueleto, o scaffolding, de un servicio.
Para crear un servicio usamos el comando "generate service", indicando a continuación el nombre del servicio que queremos generar.
ng generate service clientes
Esto nos generaría el servicio llamado "ClientesService". La coletilla "Service", al final del nombre, te la agrega Angular CLI, así como también nombra al archivo generado con la finalización "-service", para dejar bien claro que es un servicio.
Es habitual que quieras colocar el servicio dentro de un módulo en concreto, para lo que puedes indicar el nombre del módulo, una barra "/" y el nombre del servicio. Pero atención: ahora lo detallaremos mejor, pero queremos advertir ya que esto no agregará el servicio al código de un módulo concreto, sino que colocará el archivo en el directorio de ese módulo. Enseguida veremos qué tienes que hacer para que este servicio se asigne realmente al módulo que desees.
ng generate service facturacion/clientes
Ahora, si quieres, puedes echarle un vistazo al código básico de un service, generado por el CLI. Enseguida lo examinamos. No obstante, antes queremos explicar otro paso importante para que el servicio se pueda usar dentro de la aplicación.
Agregar la declaración del servicio a un módulo
Para poder usar este servicio es necesario que lo agregues a un módulo. Inmediatamente lo podrás usar en cualquiera de los componentes que pertenecen a este módulo. Este paso es importante que lo hagas, puesto que, al contrario de lo que ocurría al crear un componente con el CLI, la creación de un servicio no incluye la modificación del módulo donde lo has creado.
Así pues, vamos a tener que declarar el servicio manualmente en el módulo. Lo haremos gracias al decorador del módulo (@NgModule), en el array de "providers". El decorador de un módulo con el array de providers podría quedar más o menos así.
@NgModule({
imports: [
CommonModule
],
declarations: [ListadoClientesComponent],
providers: [ClientesService]
})
Obviamente, tendrás que hacer el correspondiente import al módulo, para que se conozca la clase ClientesService.
import { ClientesService } from './clientes.service';
Como decimos, ahora este módulo ha declarado el servicio como "provider", por lo que sus componentes podrán usar este servicio.
Código básico de un service en Angular
Ahora podemos examinar el código generado para nuestro servicio y aprender nuevas cosas de Angular. Este sería nuestro recién creado servicio "ClientesService".
import { Injectable } from '@angular/core';
@Injectable()
export class ClientesService {
constructor() { }
}
Como verás, el servicio no tiene nada todavía, solo su declaración, pero hay cosas interesantes que tenemos que explicar, principalmente un nuevo decorador que no habíamos conocido hasta el momento: "@injectable".
El decorador @injectable indica a Angular que la clase que se decora, en este caso la clase ClientesService, puede necesitar dependencias que puedan ser entregadas por inyección de depdendencias. De momento puedes quedarte que los servicios necesitan de este decorador, aunque realmente disponer de él no es condición indispensable.
El import, arriba del todo, { Injectable } from '@angular/core', lo que hace es que nuestra clase conozca y sea capaz de usar el decorador @injectable.
Por lo demás, el servicio está vacío, pero le podemos poner ya algo de código para que nos sirva de algo. De momento vamos a exponer mediante el servicio una simple propiedad con un dato, que luego vamos a poder consumir desde algún componente. Para ello usamos las propiedades de la clase, tal como nos permite TypeScript.
export class ClientesService {
accesoFacturacion = 'https://login.example.com';
constructor() { }
}
En nuestra clase ClientesService hemos creado una propiedad llamada "accesoFacturacion", en la que hemos asignado un valor que sería común para todos los clientes. El dato es lo de menos, lo interesante es ver que la declaración no dista de otras declaraciones en clases que hayamos visto ya.
Cómo inyectar dependencias de servicios
Ahora nos toca ver la magia de Angular y su inyección de dependencias, que vamos a usar para poder disponer del servicio en un componente.
Como en otros frameworks, en Angular la inyección de dependencias se realiza por medio del constructor. En el constructor de un componente, que hasta ahora habíamos dejado siempre vacío, podemos declarar cualquiera de los servicios que vamos a usar y el framework se encargará de proporcionarlo, sin que tengamos que realizar nosotros ningún trabajo adicional.
Esto es tan sencillo como declarar como parámetro la dependencia en el constructor del componente.
constructor(public clientesService: ClientesService) { }
De esta manera estamos indicando a TypeScript y Angular que vamos a usar un objeto "clientesService" que es de la clase "ClientesService". A partir de entonces, dentro del componente existirá ese objeto, proporcionando todos los datos y funcionalidad definida en el servicio.
Si defines la propiedad de la clase como pública o privada, afectará a la visibilidad del servicio. En el caso que sea "public" el servicio lo podrás usar directamente desde el template. En el caso que sea "private" podrás usar el servicio únicamente dentro del código de la clase del componente.
En ambos casos "clientesService" hará que se inyecte en el constructor un objeto de la clase ClientesService.
Explicando con detalle la declaración de propiedades implícita en el constructor
Aquí tenemos que detenernos para explicar algo de la magia, o azúcar sintáctico, que te ofrece TypeScript. Porque el hecho que se declare una propiedad en un objeto solo porque se reciba un parámetro en el constructor no es algo usual en Javascript.
Cuando TypeScript detecta el modificador de visibilidad "public" o "private" en el parámetro enviado al constructor, inmediatamente declara una propiedad en la clase y le asigna el valor recibido en el constructor. Por tanto, esta declaración:
export class ListadoClientesComponent {
constructor(public clientesService: ClientesService) { }
}
Sería equivalente a escribir todo el código siguiente:
export class ListadoClientesComponent {
clientesService: ClientesService;
constructor(clientesService: ClientesService) {
this.clientesService = clientesService;
}
}
En resumen, TypeScript entiende que, si defines la visibilidad de un parámetro en el constructor, o que quieres hacer en realidad es crear una propiedad en el objeto recién construido, con el valor recibido por parámetro.
Usando el servicio en el componente
Ahora, para acabar esta introducción a los servicios en Angular, tenemos que ver cómo usaríamos este servicio en el componente. No nos vamos a detener demasido en hacer ejemplos elaborados, que podemos abordar más adelante, solo veremos un par de muestras sobre cómo usar la propiedad declarada en el servicio.
1.- Usando el servicio dentro de la clase del componente
Dentro de la clase de nuestro componente, tendremos el servicio a partir de la propiedad usada en su declaración. En el constructor dijimos que el servicio se llamaba "clientesService", con la primera en minúscula por ser un objeto.
Pues como cualquier otra propiedad, accederemos a ella mediante la variable "this".
export class ListadoClientesComponent implements OnInit {
constructor(public clientesService: ClientesService) { }
ngOnInit() {
console.log(this.clientesService);
}
}
El ejemplo no vale para mucho, solo para mostrar que, desde que esté creado el objeto podemos acceder al servicio con "this.clientesService".
También nos sirve para recordar que, el primer sitio donde podríamos usar los servicios declarados es en el método ngOnInit(). Dicho de otro modo, si necesitamos de estos servicios para inicializar propiedadades en el componente, el lugar donde ponerlos en marcha sería el ngOnInit().
2.- Usando el servicio en el template de un componente
Por su parte, en el template de un componente, podrás también acceder al servicio, para mostrar sus propiedades o incluso invocar sus métodos como respuesta a un evento, por ejemplo.
Como el servicio está en una propiedad del componente, podremos acceder a él meditante ese nombre de propiedad. Pero ten en cuenta, que este acceso desde el template sólo será posible si el servicio se declaró con visibilidad "public".
<p>
URL De acceso: {{clientesService.accesoFacturacion}}
</p>
Conclusión a la introducción a los servicios en Angular
Eso es todo lo que tienes que saber para comenzar a experimentar con los servicios en Angular. Es momento que pongas las manos en el código y comiences a experimentar por tu cuenta, creando tus propios servicios y usándolos desde tus componentes.
En artículos posteriores veremos servicios un poco más completos, que hagan más cosas que el que hemos visto en la presente entrega. Puedes seguir aprendiendo a usar clases e interfaces en los servicios de Angular.
Miguel Angel Alvarez
Fundador de DesarrolloWeb.com y la plataforma de formación online EscuelaIT. Com...