Tutorial: Compartir datos entre componentes con un servicio
1. Objetivos de aprendizaje
Sección titulada «1. Objetivos de aprendizaje»Al terminar este tutorial vas a ser capaz de:
- Mover el
httpResourceque hoy vive en tu componente de listado hacia elArtistaServiceque ya creaste paracrear(). - Inyectar el servicio en un componente con
inject(), en vez de llamarhttpResourcedirectamente. - Explicar por qué un servicio
providedIn: 'root'es un singleton, y por qué eso permite compartir datos entre componentes que no se conocen. - Sincronizar dos componentes (
ArtistCreateyArtistList) sin@Input/@Output, usando.reload()sobre el mismo recurso compartido.
Prerrequisitos: haber completado el
tutorial de crear un artista desde el front
(ya tienes ArtistCreate, NuevoArtista y ArtistaService con crear()), y tu
componente de listado apuntando a tu propio backend, como quedó al final del
Paso 7 de “Conectar con tu front”.
2. Por qué mover el httpResource a un servicio
Sección titulada «2. Por qué mover el httpResource a un servicio»Hoy tu componente de listado hace dos cosas a la vez: pide los datos por HTTP y los muestra en el template. Funciona, pero mezcla dos responsabilidades distintas.
Hay una segunda razón, más concreta: ArtistaService ya existe (lo creó en el tutorial
anterior para crear()). Si el mismo servicio también hace la lectura, ArtistCreate y
su componente de listado van a terminar compartiendo el mismo objeto — y eso es
justo lo que necesita para que, al crear un artista, el listado se entere.
3. Renombrar tu variable de entorno
Sección titulada «3. Renombrar tu variable de entorno»Cuando creaste el environment, la variable se llamaba gistUrl porque apuntaba a un
Gist. Desde que la conectaste a tu propio backend ya no es cierto — es hora de que el
nombre lo refleje.
En src/environments/environment.ts y src/environments/environment.development.ts,
renombra la propiedad:
export const environment = { production: false, ARTISTAS_URL: 'http://localhost:8080/artistas',};4. Agregar el httpResource a ArtistaService
Sección titulada «4. Agregar el httpResource a ArtistaService»ArtistaService ya existe. Agrégale la lectura, junto a la escritura que ya tiene, y
actualiza crear() para usar la variable de entorno recién renombrada:
import { Injectable, inject } from '@angular/core';import { httpResource, HttpClient } from '@angular/common/http';import { Observable } from 'rxjs';import { Artista, NuevoArtista } from './artista.model';import { environment } from '../environments/environment';
@Injectable({ providedIn: 'root' })export class ArtistaService { private http: HttpClient = inject(HttpClient);
artistasResource = httpResource<Artista[]>(() => environment.ARTISTAS_URL);
crear(nuevoArtista: NuevoArtista): Observable<Artista> { return this.http.post<Artista>(environment.ARTISTAS_URL, nuevoArtista); }}5. Actualizar el componente de listado
Sección titulada «5. Actualizar el componente de listado»En tu componente de listado, quita el httpResource (ya no vive ahí) e inyecta el
servicio:
import { Component, inject } from '@angular/core';import { ArtistaService } from '../artista.service';
@Component({ selector: 'app-artist-list', standalone: true, templateUrl: './artist-list.component.html',})export class ArtistListComponent {
artistaService = inject(ArtistaService);}Y en el template, agrega el prefijo artistaService. en cada lugar donde antes leía el
resource directamente:
@if (artistaService.artistasResource.isLoading()) { <p>Cargando artistas…</p>}
@for (artista of artistaService.artistasResource.value() ?? []; track artista.id) { <div class="card">{{ artista.nombre }}</div>}6. Sincronizar ArtistCreate con la lista
Sección titulada «6. Sincronizar ArtistCreate con la lista»De vuelta en ArtistCreate, agregue una línea a guardar(): después de crear con
éxito, refresque el recurso compartido.
this.artistaService.crear(nuevoArtista).subscribe({ next: (): void => { this.guardando.set(false); this.exito.set(true); this.artistaForm.reset(); this.artistaService.artistasResource.reload(); }, error: (): void => { this.guardando.set(false); this.error.set(true); },});Fíjese en el orden: primero se guarda el éxito y se limpia el formulario, y solo
entonces se llama .reload(). Si el POST falla, error() se activa y .reload()
nunca se llama — no hay nada nuevo que mostrar.
En app.html, ArtistCreate y su componente de listado van uno junto al otro, como
hermanos:
<app-artist-create /><app-artist-list />Ninguno es el padre del otro, y no hay @Input/@Output entre ellos. La única
conexión es que ambos inyectan la misma instancia de ArtistaService.
7. Verificar
Sección titulada «7. Verificar»Corre tu front (ng serve) junto con tu backend. Llena el formulario y haz submit:
- El botón debería decir “Guardando…” brevemente, y luego volver a “Crear artista”.
- El formulario debería vaciarse.
- En la pestaña de Red del navegador (Network), debería ver dos peticiones seguidas: el
POST /artistasy, justo después, un nuevoGET /artistasdisparado por el.reload(). El listado no cambia de contenido todavía (su backend no persiste), pero la petición sí se repite — esa es la parte que este tutorial quiere que verifique.
Si el backend no está corriendo, pruebe primero un error a propósito: debería ver el
mensaje de error de ArtistCreate, y en ese caso el GET adicional no debería
aparecer, porque .reload() nunca se llama.
¿Dónde quedaste?
Sección titulada «¿Dónde quedaste?»Al final de este tutorial tienes:
ArtistaServiceunificado: la misma instancia lee (artistasResource) y escribe (crear()).- Tu componente de listado inyectando el servicio con
inject(), en vez de hablar directo con la red. - Tu variable de entorno renombrada de
gistUrlaARTISTAS_URL. ArtistCreatey tu componente de listado, sincronizados a través del mismo servicio singleton y.reload(), sin@Input/@Outputentre ellos.
El mismo servicio te sirve para un caso más: mostrar el detalle de un artista al hacer clic en su card, en el tutorial de ver el detalle de un artista.