Establece una comunicación entre un componente padre con uno hijo para saber qué productos quiere agregar el usuario a su carrito de compras y poder visualizar el total a pagar.
Comunicación componente hijo a padre
Paso 1: Agrégale al componente hijo un @Output() para emitir un mensaje al componente padre cuando el usuario agrega un producto al carrito.
El método addToShoppingCart() emitirá el evento cuando el usuario haga clic en el botón.
<!-- components/producto/producto.component.html --><div><h2>{{ producto.name }}</h2><img[src]="producto.image"width="200px"height="200px"><p>Precio: {{ producto.precio }}</p><button(click)="addToShoppingCart(producto)">Agregar al carrito</button></div>
Paso 2: En el componente padre crea un método para recibir el mensaje, agregarlo al carrito de compras y calcular el monto total a pagar.
// catalogo/catalogo/catalogo.component.ts@Component({selector:'app-catalogo',templateUrl:'./catalogo.component.html',styleUrls:['./catalogo.component.scss']})exportclassCatalogoComponent{publicshoppingCart:Producto[]=[];public total =0;publicproductos:Producto[]=[/* ... */];addProductToCart(p:Producto):void{this.shoppingCart.push(p);this.total+= p.precio;}}
Paso 3: El método addProductToCart() recibe el producto, lo guarda en el array shoppingCart y calcula el total a pagar por el usuario. Puedes imprimir estos valores fácilmente con una interpolación.
<!-- catalogo/catalogo/catalogo.component.ts --><div*ngIf="productos"class="catalogo"><app-producto*ngFor="let p of productos"[producto]="p"(addProduct)="addProductToCart($event)"></app-producto></div><div><h3>Cantidad: {{ shoppingCart.length }}</h3><h3>Total a pagar: {{ total }}</h3></div>
La comunicación de componente es escencial en cualquier aplicación front-end. Es importante saber manipular el envio de información ya sea de forma descendente o ascendente en la jerarquía de componentes.
Contribución creada con los aportes de Kevin Fiorentino.
Muy bien estructurado el curso para ir integrando y prácticando las características de angular
Tienes razón, Nicolás es muy buen profesor, el tema de Componentes esta claro, vamos por el resto del Framework.
menos mal veo comentarios como los de ustedes jaja, es verdad, y algunos no logran dimensionar lo excelente que ha sido el curso, mi pregunta es si están estudiando bien ? o se vuelan los cursos sin generar aprendizaje, es que ami me ha parecido maravilloso hasta ahora, estos cursos y el de manipulación de arrays son la bibilia del frontend jajaja
Otra manera de ir sumando el total:
this.total+= product.price;
El tema con esa implementación es que si se quitará un item del carrito el total no se actualizaría o habría que agregar más líneas de código para hacerlo funcionar correctamente
jajaja también lo apliqué así.
Sabes que todo va a salir bien cuando el profe usa el método reduce😎😎
En verdad Nicolas me asombra con el manejo de arrays y los metodos que usa, el mismo metodo que utilizo para sumar totales, yo lo trate de hacer y eran 5 lineas, mientras que el la hizo en 1
Gracias Nico, eres grande!!!
Así es, se le nota que tiene un nivel muy avanzado, y es gratificante tenerlo como profesor. Ojalá absolutamente todos los profes de Platzi fueran así de Pro.
Está muy bueno este curso. Aprendí Angular en Udemy hace un tiempo, pero esta serie de cursos me resulta genial para refrescar algunos conceptos clave.
Buenos días:
Tengo una duda, que es mejor usar, input y outpus o usar redux (ngRX), o simplemente esto depende de la aplicación. En el ejemplo del carrito de compras que seria mejor usar, o cualquier opción esta bien?
Creo que todo depende de lo grande de la aplicación. Y los requerimientos. Pero en lo personal aún no sé cuándo ya es necesario implementar un estado para la aplicación
se pueden hacer metodos para formatear el precio, como en vue por ejemplo?
formatNumber(total)
formatNumber {
//codigo
}
Si se puede hacer metodos para formatear el precio, pero Angular es un framework muy poderoso que te permite crear tus propias funciones y métodos personalizados que se pueden usar en cualquier lugar de tu aplicación. Una forma común de crear una función para formatear un número es crear un "pipe" (tubería) personalizado.
import{Pipe,PipeTransform}from'@angular/core';@Pipe({name:'formatNumber'})exportclassFormatNumberPipeimplementsPipeTransform{transform(value: number): string {// Convertir el número a una cadena con dos decimalesconst formattedNumber =Number(value).toFixed(2);// Agregar comas como separadores de milesconst parts = formattedNumber.toString().split('.'); parts[0]= parts[0].replace(/\B(?=(\d{3})+(?!\d))/g,",");return parts.join('.');}}
En el ejemplo anterior, se crea una clase de pipe personalizado llamada FormatNumberPipe. El método transform acepta un valor numérico como entrada y devuelve una cadena de texto con el número formateado con comas como separadores de miles y dos decimales.
Para usar el pipe en tu aplicación, solo tienes que incluirlo en el módulo donde quieras usarlo y luego llamarlo desde tu plantilla:
htmlCopy code
<!--Ejemplo de uso del pipe en una plantilla --><p>El precio total es:{{ total | formatNumber }}</p>
En este ejemplo, total es el valor numérico que quieres formatear y formatNumber es el nombre del pipe personalizado que acabas de crear.
Aun que claro, Angualr ya tiene pipes predefinidos para algunos casos especificos, te dejo el link donde los puedes ver sin necesidad de tener que crear la clase Pipes Angular
pregunta, (ojala algún día sea contestada ^.^) ¿Cómo puedo hacer para que al recargar la pagina los productos agregados al carrito entre otras variables no se reinicien o no se borren?(como en linio y otras web de compras) Gracias por sus respuestas
uno , interactuando con una base de datos
otra forma es con el localstorage
La mejor forma seria con el localStorage del navegador, y al recargar la pagina, cargar los valores del storage, y después de verificar si hay elementos, cargar los componentes.
Así lo haría yo.
Excelente primer módulo! Todo está muy bien explicado, Gracias!
El Concepto de componentes y de lo que podemos hacer con ellos me quedo muy claro con este curso
Es más correcto usar el reduce que hacerlo así?
onAddToShoppingCart(product: Product){
this.myShoppingCart.push (product);
this.total = this.total + product.price;
}
entoendo que sí, pero por qué?
Sí, es más correcto usar el método reduce en lugar de hacerlo de esa manera. El método reduce permite reducir un array a un solo valor utilizando una función reductora. En este caso, podrías utilizar reduce para sumar los precios de los productos en el carrito de compras y obtener el total de manera más concisa y eficiente.
la verdad no entiendo como hace la suma del precio ?
myShopingCart:Product[]=[];onAddToShopingCart(product:Product){this.total=this.myShopingCart.reduce((sum, item)=> sum + product.price,0);}
Este código calcula el total de una lista de productos en un carrito de compras. Aquí hay una explicación detallada de lo que sucede en cada parte del código:
this.myShoppingCart se refiere al carrito de compras, que es un objeto que contiene una lista de productos.
reduce() es un método de array que se utiliza para reducir los elementos de un array a un único valor. En este caso, se utiliza para sumar los precios de todos los productos en el carrito.
(sum, item) es una función de reducción que se utiliza para acumular el total de precios. En cada iteración, sum representa el acumulador, es decir, el valor acumulado hasta el momento, y item representa el siguiente elemento en la lista, que en este caso es un objeto que contiene información sobre un producto.
sum + product.price es la operación que se realiza en cada iteración de reduce(). product.price se refiere al precio del producto actual, y se suma al acumulador sum. Al final de la iteración, el nuevo valor de sum se utiliza en la siguiente iteración como el acumulador actualizado.
0 es el valor inicial del acumulador. En la primera iteración, sum se establece en este valor y luego se actualiza en cada iteración.
Por lo tanto, al final de la reducción, this.total contendrá la suma de los precios de todos los productos en el carrito.
alguien más tuvo problemas con los estilos?? mi carrito de compras desapareció en mobile
Podrias Compartirnos el codigo ?
de donde sale "item" ? no entendi bien la funcion " .reduce((sum, item) => sum + item.price, 0); " alguien me la podria explicar bien?
El método reduce recibe una función como parámetro. A esa función puede recibir cuatro parametros, que puedes nombrar de "cualquier forma":
El acumulador
El valor actual
El índice actual
El array
Esos parametros los recibe del reduce.
En este caso .reduce((sum, item) => sum + item.price, 0), item es el valor actual que esta procesando el reduce y sum el valor acumulado.
Tu puedes cambiarle el nombre y funcionará igual. Lo importante es la cantidad de parametros que declaras en la función dentro del reduce, pues serán los parametros que recibiras por parte del reduce. 🤓🍍🍍
engo una duda con respecto al EventEmite<Product>()
<Product> es el tipo de dato que le vamos a pasar al EventEmiter como se llama esto referencia Generica?
¡Excelente pregunta!
En TypeScript, <Product> es un ejemplo de lo que se conoce como "tipo genérico" o "parámetro de tipo genérico". Los tipos genéricos permiten que una función o una clase trabajen con diferentes tipos de datos sin tener que definir un tipo específico para cada caso.
En el caso de EventEmitter<Product>, Product es el parámetro de tipo genérico que se utiliza para indicar el tipo de dato que se va a emitir a través del EventEmitter. En otras palabras, Product es un tipo de dato genérico que se reemplaza con un tipo de dato específico en tiempo de ejecución.
Al utilizar tipos genéricos, puedes crear funciones y clases reutilizables que trabajen con diferentes tipos de datos sin tener que escribir una versión separada para cada tipo de dato. Esto hace que tu código sea más genérico y escalable, lo que puede ahorrar tiempo y esfuerzo en el largo plazo.
Si estan con angular 17 y tienen el problema de que no les actualiza la cantidad y el total, la forma que lo pueden solucionar es usando un signal en total. Y en la funcion hacerle el set del reduce al total.
Desde este punto ya pueden empezar a realizar proyectos con Angular
También podemos validar que en el carrito de compras no hayan productos repetidos, comprobando cuando vayamos a añadir un producto al carrito, que dicho producto no haya sido añadido al carrito anteriormente:
addedProducts:Product[]=[];//CARRITO DE COMPRAStotalPrice: number =0;//PRECIO TOTAL DEL CARRITO DE COMPRASonAddToShoppingCart(productAdded:Product){// VERIFICAMOS QUE EL PRODUCTO NO ESTÉ YA DENTRO DEL CARRITO DE COMPRASif(this.addedProducts.includes(productAdded)){console.log("El producto ya ha sido agregado al carrito");}else{this.addedProducts.push(productAdded);//RECALCULAMOS EL VALOR TOTAL DEL PRODUCTO DE COMPRAS://this.totalPrice += productAdded.price;this.totalPrice=this.addedProducts.reduce((sum, product)=> sum + product.price,0);}console.log(this.addedProducts);console.log("TOTAL:",this.totalPrice);}}
Cada día más emocionado con este curso. Muchas gracias Nicolas.