Actividad entregable

7. Alta y Eliminación de Productos

7.1. Preparar el ProductService

Vamos a convertir ProductService en el centro del estado de la aplicación.

Es decir, será el responsable de almacenar la lista de productos, añadir nuevos y eliminar los existentes. Es necesario para que todos los componentes tengan la lista actualizada y la pantalla se refresque automáticamente,

BehaviorSubject es el corazón de nuestra aplicación. Es donde vive la lista de productos, y cada vez que la modificamos (añadiendo, eliminando o filtrando) la aplicación entera se actualiza automáticamente.

BehaviorSubject = es como una mini-base-de-datos dentro del servicio

Abrimos product.service.ts y añadimos BehaviorSubject:

import { BehaviorSubject } from 'rxjs';

Debajo del url:

private productosSubject = new BehaviorSubject<Product[]>([]);
productos$ = this.productosSubject.asObservable();

private productosOriginales: Product[] = [];

private productosSubject = new BehaviorSubject<Product[]>([]);
productos$ = this.productosSubject.asObservable();

private productosOriginales: Product[] = [];

productosOriginales será nuestra lista interna.

productos$ es un observable que enviará los cambios a los componentes automáticamente.

Esto es esencial para que, cuando creemos o eliminemos un producto, la lista se actualice sola.

Modificar cargarProductos() para usar BehaviorSubject

Cuando llegan los productos desde la API, los guardamos internamente y los notificamos a toda la aplicación mediante next().

Reemplaza cargarProductos():

cargarProductos() {
  this.http.get<Product[]>(this.url).subscribe({
    next: (productos) => {
      this.productosOriginales = productos;
      this.productosSubject.next(productos);
    },
    error: (err) => console.error('Error al cargar productos:', err)
  });
}

cargarProductos() {
  this.http.get<Product[]>(this.url).subscribe({
    next: (productos) => {
      this.productosOriginales = productos;
      this.productosSubject.next(productos);
    },
    error: (err) => console.error('Error al cargar productos:', err)
  });
}

Implementar agregarProducto()

Aquí viene algo importante, en un proyecto real, el ID del producto lo genera el backend cuando hacemos un POST.

Pero nuestra API solo permite lectura, no creación y Angular no tiene forma de pedir un ID nuevo al servidor.

Por eso podemos usar UUID. Es una pequeña ‘trampilla’ que sirve para simular el comportamiento real de un backend y poder añadir, identificar y eliminar productos correctamente.

Las versiones modernas de JavaScript incluyen crypto.randomUUID(), que nos genera un ID único automáticamente.

_id: crypto.randomUUID(),   //  la “trampilla”

Quedaría así:

agregarProducto(datos: any) {

  const nuevoProducto: Product = {
    _id: crypto.randomUUID(),   // Generamos un ID único (trampilla)
    name: datos.name,
    description: datos.description,
    price: datos.price,
    category: datos.category,
    image: datos.image,
    active: datos.active
  };

  // Añadimos el nuevo producto al principio de la lista
  this.productosOriginales = [nuevoProducto, ...this.productosOriginales];

  // Emitimos la nueva lista para que Angular actualice la vista
  this.productosSubject.next(this.productosOriginales);
}

  agregarProducto(datos: any) {

    const nuevoProducto: Product = {
      _id: crypto.randomUUID(),   // Generamos un ID único (trampilla)
      name: datos.name,
      description: datos.description,
      price: datos.price,
      category: datos.category,
      image: datos.image,
      active: datos.active
    };

    // Añadimos el nuevo producto al principio de la lista
    this.productosOriginales = [nuevoProducto, ...this.productosOriginales];

    // Emitimos la nueva lista para que Angular actualice la vista
    this.productosSubject.next(this.productosOriginales);
  }
Implementar eliminarProducto()

Eliminar un producto es tan simple como filtrar la lista interna y volver a emitir el cambio. Angular actualizará automáticamente la pantalla.

Añadir al servicio:

eliminarProducto(id: string) {
  this.productosOriginales = this.productosOriginales.filter(p => p._id !== id);
  this.productosSubject.next(this.productosOriginales);
}