Creación y Reutilización de Componentes en Angular para Tiendas
Resumen
Existen muchas situaciones en donde deberás enviar información de un componente padre a su/s hijo/s, por eso, acá te mostraremos con un ejemplo cómo funciona el componente para producto.
Comunicando componente padre a hijo
Un ejemplo real para el uso de la comunicación entre componente podría ser para renderizar N cantidad de productos de un catálogo.
Paso 1: Comienza creando una interfaz para tipear el modelo de datos del Producto:
Paso 2: Luego, impórtala en el componente Catálogo que será el componente padre en la comunicación.
// components/catalogo/catalogo.component.tsimport{Component}from'@angular/core';import{Producto}from'./producto.interface.ts';@Component({selector:'app-catalogo',templateUrl:'./catalogo.component.html',styleUrls:['./catalogo.component.scss']})exportclassCatalogoComponent{publicproductos:Producto[]=[{id:1,name:'Automobil de juguete',precio:100,image:'./image1.jpg'},{id:2,name:'Muñeca de trapo',precio:180,image:'./image2.jpg'},{id:3,name:'Pelota de futbol',precio:120,image:'./image3.jpg'}];}
Paso 3: Este componente posee un array de productos para iterar en el HTML inicializando el componente <app-producto> por cada objeto en el array.
<!-- components/catalogo/catalogo.component.html --><app-producto*ngFor="let p of productos"[producto]="p"></app-producto>
Paso 4: Finalmente, el componente hijo recibe el producto haciendo uso del decorador @Input() y apoyándose también de la interfaz para tipear los datos.
Será habitual tener la necesidad en tus proyectos de construir componentes más grandes o "contenedores" de muchos otros componentes repetitivos y más pequeños. Es importante buscar este desacople entre componentes de la mejor manera posible.
La forma de inicializar el producto al inicio para que no marque un error está genial, sin embargo, también podemos evitar el error con la siguiente sintaxis:
@Input('product') product!:Product;
con el signo de exclamación le decimos a Angular (o Typescript) que esa propiedad si va a existir, que no puede ser nula, así que no te preocupes, verás que si la tengo jejeje.
Genial! una solución bastante limpia
Así es, es la manera en como yo inicializo, no sé si sea la mejor practica, pero es la que se me hizo más rápida
array
[{id:'1',name:'EL mejor juguete',price:565,image:'./assets/images/toy.jpg'},{id:'2',name:'Bicicleta casi nueva',price:356,image:'./assets/images/bike.jpg'},{id:'3',name:'Colleción de albumnes',price:34,image:'./assets/images/album.jpg'},{id:'4',name:'Mis libros',price:23,image:'./assets/images/books.jpg'},];
Que eficiencia!!
te quiero mucho persona que hizo esto
Array
products:Product[]=[{id:'1',name:'EL mejor juguete',price:565,image:'https://static.platzi.com/media/user_upload/toy-a0d1c980-a8ce-4fa4-83d6-3b016999a162.jpg'},{id:'2',name:'Bicicleta casi nueva',price:356,image:'https://static.platzi.com/media/user_upload/bike-143dcfe9-3190-49fd-88f7-d3bf74182072.jpg'},{id:'3',name:'Colleción de albumnes',price:34,image:'https://static.platzi.com/media/user_upload/books-80160e05-d177-420b-89c5-01a97b2bdb76.jpg'},{id:'4',name:'Mis libros',price:23,image:'https://static.platzi.com/media/user_upload/album-6f4213d5-1d2d-4e0f-96fe-edb36c3255b4.jpg'},{id:'5',name:'Casita michi',price:125,image:'https://static.platzi.com/media/user_upload/house-034b0c04-eeff-42fa-b506-79f18f73ff90.jpg'},{id:'6',name:'Lentes vintage',price:82,image:'https://static.platzi.com/media/user_upload/glasses-05350737-5831-4c98-be55-824399206dba.jpg'},];
Gracias
Ojo a la muñeca, que no vaya a levantarse de repente de esa caja 🤭
estos tipos de Inputs y Outputs nos servirán bastante en modales o Pop Up
Así vamos 🤘
 haga su funcion y al final del dia unimos todo
¿la carpeta models tiene siempre que estar al nivel de la carpeta components?, ¿si la aplicación es muy grande no es mejor que cada componente maneje sus propios modelos????
realmente no importa donde los pongas, lo que importa es conocer la ruta para cuando los tengas que importar, sin embargo, si un mismo model es compartido por varios componentes, sería entonces más cómodo tenerlo en un nivel más arriba que el componente
No, no es necesario que este al mismo nivel. Y como bien lo dices para proyectos grandes se manejen carpetas diferentes. Lo realmente importante es saber como llegar a la ruta, saludos.
En el curso de Frontend Developer con Estefany, hicimos esas vistas. Me las copié, sirvió!
Les dejo las dos imagenes por si las quieren descargar
Estoy intentando hacer exactamente lo mismo traer del padre un objeto llamado peopleList. Este solo tendría datos como "name" y "birth"
Porfavor porfavor un ayudita a entender el por que ocurre esto.
Tienes un error en el valor que recibe el input en el componente padre, estás enviado peopleList y debería ser data que es el que se define en el ngFor, esta sería la forma correcta:
<app-birthday-records [data]="data"*ngFor="let data of peopleList"></app-birthday-records>
También te recomendaría mejorar el nombre de los objetos, como por ejemplo en la definición del Input no hace falta el bindingPropertyName ++data++, un nombre adecuado sería ++people++ ya que recibe un objeto individual y no una lista de ellos, esto con el fin de buenas prácticas, mejorar comprensión del código y minimizar errores.
@Input people:People={name:'',birth:'',};
Y también modificar el componente padre:
<app-birthday-records [people]="people"*ngFor="let people of peopleList"></app-birthday-records>Saludos!
Resumen de la clase:
se crea el componente de product, adicionalmente se crea una interfaz(modelo) para tipar la información del producto.
En el HTML del componente del product se crea la estructura para ver la información de los productos.
En el componente HTML del padre se adiciona el selector del componente product, adicionalmente en el selector se realiza un ngFor para iterar los productos y se realiza un binding con la variable del producto del TS del componente product. EJP:
<app-product [product]="product" *ngFor="let product of products"></app-product>
En el TS del componente Padre app se crea un objeto que tiene la información de los productos tapándolo con el modelo de product que se creo al principio.
Con lo de la declaración de un estado inicial, las diferentes maneras para lograr el resultado, evaluando la que mas se adapte a los intereses del desarrollo
Componente para producto
Primero creamos la interfaz del producto, en product.model.ts:
import{Component}from'@angular/core';import{Product}from'./models/product.model';@Component({ selector:'app-root', templateUrl:'./app.component.html', styleUrls:['./app.component.scss']})exportclassAppComponent{ imgParent =''; products:Product[]=[{ id:'1', name:'EL mejor juguete', price:565, image:'./assets/images/toy.jpg'},{ id:'2', name:'Bicicleta casi nueva', price:356, image:'./assets/images/bike.jpg'},{ id:'3', name:'Colleción de albumnes', price:34, image:'./assets/images/album.jpg'},{ id:'4', name:'Mis libros', price:23, image:'./assets/images/books.jpg'},];onLoaded(img:string){console.log('log padre!', img);//* img viene del hijo}}
y lo renderizamos en el html de product.component.html:
<app-product*ngFor="let product of products"[product]="product"></app-product>
Nota: la parte de [product]="product" se entiende por el *ngFor.
Bastante interesante!
se podría considerar los siguiente una buena práctica para inicializar los productos:
@Input product: Product = {} as Product;
donde Product es nuestra interface
La forma en que escribes no es correcta, la probé para estar seguro y el compilador muestra un error.
Al escribir
product:Product
Ya estas informando al compilador que la variable product es de tipo Product.
Por otro lado en el ejemplo dado por el profesor Product te obliga a inicializar el objeto y la sentencia completa queda así:
es completamente valido en código. hace parte de type assertion, pero al usar esa sintaxis vas a perder seguridad de tipado ya que podrías llegar a tener valores undefinded, y posiblemente errores en tiempo de ejecución, al acceder a las propiedades de la interfaz.
https://www.typescriptlang.org/docs/handbook/2/everyday-types.html#type-assertions