Los componentes NO deben obtener o guardar datos directamente y no deben presentar datos falsos. Los componentes deben centrarse en presentar datos y delegar el acceso a los datos a un servicio.
Un servicio es un proveedor de datos, que mantiene lógica de acceso a ellos. 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.
Utiliza el proyecto que desarrollaste con los tutoriales de Angular - Local, Angular - Boostrap, Angular - Componentes, Comunicación y Directivas
Para consultar datos mediante servicios, es recomendable el uso de interfaces para reconocer su estructura. Desde la raíz del proyecto con Angular
Cree la interfaz Foto, con: ng generate interface interfaz/foto
Identifique la estructura de la respuesta del servicio a consultar para definir los atributos de la interfaz de respuesta. Según el recurso Foto la estructura es:
export interface Foto {
descripcion: string;
id: string;
url: string;
}
Desde la raíz del proyecto con Angular
ng generate service servicios/recursos
recursos.service.ts
y recursos.service.spec.ts
Las dependencias son servicios u objetos que una clase necesita para realizar su función. La inyección de dependencia (DI) es un patrón de diseño en el que una clase solicita dependencias de fuentes externas en lugar de crearlas, para aumentar la flexibilidad y modularidad en sus aplicaciones. Angular proporciona dependencias a una clase en la creación de instancias.
Para inyectar una dependencia en un componente solo debes agregar un argumento (con el tipo de la dependencia) en el método constructor de la clase.
...
import { Component } from '@angular/core';
import { RecursosService } from './servicios/recursos.service';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
...
...
imports: [ ... ],
providers: [RecursosService],
templateUrl: '...',
...
...
export class AppComponent {
constructor(private recursosService: RecursosService) {}
}
...
Las aplicaciones en el front-end necesitan comunicarse con un servidor a través del protocolo HTTP, para descargar o cargar datos y acceder a otros servicios back-end. Angular proporciona una API HTTP de cliente para aplicaciones Angular, la clase de servicio HttpClient
en @angular/common/http
.
Para este caso, Angular usa los observables
en lugar de promesas para entregar valores de forma asíncrona.
HttpClientModule
...
import { HttpClientModule } from '@angular/common/http';
...
@Component({
selector: 'app-root',
standalone: true,
imports: [ ... HttpClientModule ... ],
...
HttpClient
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
@Injectable({
providedIn: 'root'
...
HttpClient
como inyección de dependencia en el método constructor.
...
export class RecursosService {
constructor(private http: HttpClient) { }
...
}
http
para obtener get
una respuesta del URL Fotos
...
constructor(private http: HttpClient) { }
...
obtenerDatos() {
return this.http.get('https://dawm-fiec-espol-default-rtdb.firebaseio.com/photos.json')
}
...
Ahora, para acabar esta introducción a los servicios en Angular, tenemos que ver cómo usaríamos el servicio RecursosService en el componente AppComponent.
...
import { Foto } from './interfaz/foto';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
...
...
export class AppComponent {
fotos: Foto[] = [];
constructor(private recursosService: RecursosService) {
}
}
...
Modifique el constructor para suscribirse a la respuesta del servicio
...
export class AppComponent {
fotos: Foto[] = [];
constructor(private recursosService: RecursosService) {
recursosService.obtenerDatos().subscribe(respuesta => {
this.fotos = respuesta as Array<Foto>
})
}
}
...
Reemplace el contenido de:
<div class="album py-5 bg-light">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
...
</div>
</div>
</div>
Por el arreglo fotos renderizado con la directiva @for, o *ngFor.
<div class="album py-5 bg-light">
<div class="container">
<div class="row row-cols-1 row-cols-sm-2 row-cols-md-3 g-3">
@for (foto of fotos; track foto.id) {
<div class="col">
<div class="card shadow-sm">
<img src="{{foto.url}}" alt="{{foto.id}}">
<div class="card-body">
<p class="card-text">{{foto.descripcion}}</p>
<div class="d-flex justify-content-between align-items-center">
<div class="btn-group">
<button type="button" class="btn btn-sm btn-outline-secondary">View</button>
<button type="button" class="btn btn-sm btn-outline-secondary">Edit</button>
</div>
<small class="text-muted">9 mins</small>
</div>
</div>
</div>
</div>
}
</div>
</div>
</div>