Crea una cuenta y continúa aprendiendo 🚀

Regístrate o inicia sesión para continuar aprendiendo:

Frontend Aprendiz

CartDetail: Comunicación entre hermanos

En esta lección agregamos una interface y un componente nuevo para representar al detalle de nuestro carrito de compras. Así mismo, cómo podemos comunicar componentes hermanos, que se encuentran a un mismo nivel.

Comunicación entre Componentes Hermanos

Ya hemos visto cómo enviar datos desde un componente padre a un componente hijo a través de props y cómo recuperar datos desde un componente hijo hacia un componente padre a través de eventos.

Sin embargo, este componente padre solamente tiene un único componente hijo. ¿Cómo podemos hacer que dos componentes "sibling" (hermanos, es decir, al mismo nivel) se comuniquen?

En ese caso, simplemente usamos lo que ya conocemos. Una vez que la información esté en el componente padre, enviamos eso hacia el otro componente distinto a través de props.

Creación del Componente Cart.vue

Por ejemplo, en este caso tenemos productos. Vamos a agregar un componente nuevo representando al carrito de compras.

  1. Creamos un nuevo archivo llamado Cart.vue.
  2. Agregamos una sección de script con lang=ts.
  3. Agregamos también una etiqueta template.

Nuestro carrito de compras será sencillo. Solo mostrará los productos agregados.

Estructura del Componente

  • Un párrafo: "Productos agregados al carrito".
  • Una lista ul con elementos li que mostrarán los productos y sus cantidades.
  • Iteramos una variable llamada details usando v-for.
<ul>
  <li v-for="detail in details" :key="detail.productId">
    Producto {{ detail.productId }} - Cantidad: {{ detail.quantity }}
  </li>
</ul>

Definición de data y Tipado de details

Estamos usando la sintaxis de Options API, por lo que definimos data como un método que retorna un objeto con el estado del componente.

export default {
  data() {
    return {
      details: [] // Inicialmente vacío
    };
  }
};

Cada vez que agreguemos productos, este arreglo almacenará los detalles.

Sin embargo, obtenemos un error porque intentamos acceder a productId, pero aún no hemos definido su estructura. Para solucionarlo:

  1. Creamos una interfaz CartDetail.
  2. Definimos productId y quantity como números.
  3. Guardamos esta interfaz en product.ts (lo renombramos como tipos.ts).
interface CartDetail {
  productId: number;
  quantity: number;
}

Ahora, importamos CartDetail en Cart.vue y tipamos details:

details: CartDetail[] = [];

Así, ya podemos acceder correctamente a productId y quantity.

Envío de Información desde ProductList a Cart

Como la información proviene de ProductList, definimos details como una prop en Cart.vue:

props: {
  details: {
    type: Array as PropType<CartDetail[]>,
    required: true
  }
}

Luego, eliminamos la variable de estado details, ya que ahora viene como una prop.

En el componente padre (ProductList.vue):

  1. Importamos Cart.vue.
  2. Lo registramos como un componente.
  3. Le pasamos details como prop, inicialmente con un arreglo vacío.
<Cart :details="details" />

Para probarlo, pasamos un objeto con productId: 3 y quantity: 100:

details: [{ productId: 3, quantity: 100 }]

Al actualizar, veremos que el producto 3 ha sido agregado 100 veces.

Manejo Dinámico de details

En lugar de definir manualmente el arreglo details, lo gestionamos dentro del estado del componente:

data() {
  return {
    details: [] as CartDetail[]
  };
}

Cuando se haga clic en el botón "Agregar", se ejecutará ProductAdded, que añadirá nuevos elementos:

this.details.push({ productId, quantity });

Ahora, cada vez que se agregue un producto, aparecerá en Cart.vue.

Problema con Productos Duplicados

Si agregamos el mismo producto más de una vez, en lugar de sumar cantidades, se crea una nueva entrada.

Esto lo corregiremos en la siguiente lección.

Esta lección no cuenta con recursos adicionales.

Si crees que hace falta algo, o necesitas ayuda, puedes publicar una pregunta en el foro.

Ya hemos visto como enviar datos desde un componente padre a un componente hijo a través de props y como recuperar datos desde un componente hijo hacia un componente padre a través de eventos. Sin embargo, este componente padre solamente tiene un único componente hijo. ¿Cómo podemos hacer que dos componentes "sibling", o sea dos componentes hermanos que están al mismo nivel se comuniquen? En ese caso, simplemente usamos lo que ya conocemos. Una vez que la información esté en el componente padre, enviamos eso hacia el otro componente distinto a través de props. Por ejemplo, en este caso tenemos productos. Vamos a poner aquí debajo un componente nuevo representando al carrito de compras. Entonces vamos a crear un nuevo archivo. Este archivo lo vamos a llamar "Cart.vue". Vamos a agregar aquí una sección de script con "lang=ts" y vamos a agregar también una etiqueta template. Nuestro carrito de compras va a ser super sencillo. Simplemente nos va a decir qué productos tenemos agregados. Entonces vamos a poner un párrafo que dirá “Productos agregados al carrito”. Luego vamos a tener un "ul" y por cada “li” vamos a mostrar qué producto tenemos y en qué cantidad. Entonces vamos a poner por aquí un "v-for" y vamos a iterar una variable llamada "details" con los detalles que están agregados al carrito. Por aquí vamos a poner un "expor default" con un objeto, ya que estamos usando la sintaxis de Options API, y vamos a empezar definiendo "data". "Data" es un método que va a retornar un objeto con el estado de este componente. El estado de este componente va a estar determinado por unos detalles que al inicio será un arreglo vacío y conforme vayamos agregando productos van a ir apareciendo por aquí más detalles. Entonces “details in details” nos va a permitir iterar este arreglo y lo único que vamos a hacer por ahora es imprimir el id del producto y la cantidad de veces que se ha agregado este producto. Como vemos aquí, nos marca un error porque estamos tratando de acceder una propiedad “productId”, pero nunca hemos definido qué tipo de datos van a estar contenidos en este arreglo. Para esto vamos a necesitar un tipo de dato, así como tenemos Product, vamos a agregar una interfaz más que se va a llamar. Vamos a agregar una interfaz más que se va a llamar “CartDetail”. Este “CartDetail” va a contener un “productId”, que viene a ser un número y una cantidad, que viene a ser también un número. Estamos definiendo nuestras interfaces dentro de un archivo “product.ts”, pero entonces vamos a renombrar este archivo para que se llame “tipos”. Entonces, tras hacer este cambio, automáticamente Visual Studio Code actualiza los import según corresponde. Volviendo a nuestro Cart, vamos a importar por aquí un tipo de dato que en este caso es “CartDetail”. Lo importamos y ahora vamos a usarlo aquí. Antes del arreglo vamos a indicar a través de este operador diamante cuál es el tipo de dato de details. Details es un array de tipo “CartDetail”. Aquí lo tenemos. Debemos tener cuidado. Tenemos un menor y un mayor encerrando al tipo de dato. Y el tipo de dato es “array” encerrando “CartDetail”. Una vez tengamos ello, como ya estamos diciendo que este arreglo va a contener objetos de este tipo, ya nos permite aquí acceder a “productId” y también a la cantidad. Para imprimir la cantidad, también es importante encerrar esto entre llaves. Las llaves son necesarias para imprimir el valor de una variable. En este caso imprimimos el id del producto y luego la cantidad. Ya tenemos aquí definido nuestro componente “cart”. Lo siguiente es enviarle esta información a “cart.” Como la información va a venir desde “ProductList”, vamos a definir los detalles como props más bien. Entonces vamos a tener aquí un “details” con un tipo. ¿Cuál es el tipo? Vamos a tener los detalles con un tipo y vamos a decir que es requerido. El tipo será “object” y de manera específica será de este tipo de dato. Para poder definir el tipo de dato de una propiedad. Ya hemos visto que tenemos que usar prop type, entonces usamos "prop type" e indicamos aquí el tipo de dato. Tras hacer esto, ya podemos borrar esta variable de estado y lo estamos declarando más bien ahora como props. Entonces nuestro componente “cart” puede recibir “details” siguiendo esta declaración. Por lo tanto, vamos a agregar aquí nuestro componente “cart” y le vamos a pasar como “details” un arreglo vacío. Para que esto funcione, tenemos que declarar el componente “cart”, eso también ya hemos visto como hacerlo. Vamos a ponerle aquí una coma y vamos a importar que el componente “cart”, para importarlo simplemente accedemos de esta manera. Hasta aquí guardamos y al actualizar vemos que no hay ningún producto. Por ahora de manera constante vamos a pasar un objeto que tendrá una propiedad “productId: 3” y “quantity: 100”. Solamente para hacer una prueba. Volviendo al navegador, vemos efectivamente que tenemos el producto tres agregado 100 veces. Aquí podemos escribir la palabra “producto” y este será el resultado, el producto tres ha sido agregado 100 veces. Esto funciona bien. Demuestra que podemos enviar datos desde “ProductList” hacia “cart”. Sin embargo, este arreglo lo estamos definiendo nosotros y no debería ser así. Así como tenemos dentro de "data" una variable de estado llamada products, vamos a agregar una variable de estado más llamada “details”. “Details” detail es un arreglo y usando este operador diamante, vamos a indicar aquí de qué tipo de dato estamos hablando. Específicamente, estamos hablando de un arreglo de tipo “CartDetail” y su valor inicial será un arreglo vacío. Pero conforme se llame al método, un “ProductAdded”, nosotros vamos a ir agregando más elementos con “details.push”, nosotros vamos a agregar nuevos objetos al arreglo. Vamos a indicar cuál es el “productId” y vamos a indicar también cuál es la cantidad. Con esto, cada vez que se haga clic sobre el botón de agregar en uno de los Cards, eso se propagará y nosotros agregaremos un elemento nuevo a nuestro arreglo de detalles. Finalmente, tenemos que enviar aquí “details”, es decir, la variable de estado que hemos definido. Entonces actualizamos. Vamos a agregar un micrófono y aquí aparece el producto 12 “se ha agregado una vez” nos dice. Agregamos un monitor y agregamos una silla. Sí. Sin embargo, si yo vuelvo a seleccionar un producto que ya tengo agregado, en vez de sumarse, se está agregando una vez más. Eso es algo que podemos corregir fácilmente. Veámoslo en la lección siguiente.

¿Tienes dudas?

Publicar pregunta

¡Comparte conocimiento!

X

Volver al índice

Regístrate

Inicia sesión para llevar un control de tu progreso.

Capítulos








































40

CartDetail: Comunicación entre hermanos




















































































Espera un momento 🎁 ...

¿Te gustaría aprender a programar, gratis?

Mago de Programación y más

Sólo debes registrarte 😉.