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.
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'},];
Hola, es una gran pregunta y si es una opción, es decir si se puede generar una clase en donde también estén esos métodos sin embargo eso hace que tengamos que hacer un proceso más desde el lado de frontend es decir cuando una API nos retorne la información en JSON tendemos que recorrer cada uno y volverlo una clase lo cual añade procesamiento, lo más normal es que el backend ya envíe los datos procesados y nosotros solo hacemos el render. Las transformaciones si son formatos de cara al render es mejor hacerlo por medio de pipes.
Aquí una lectura recomendada sobre interfaces vs clases.
Hola esto tiene que ver más con un patrón de arquitectura en donde separamos responsabilidades de un componente contenedor y un componente prestacional, el componente contenedor encarga de cosas más lógicas como obtener la información, el componente prestacional solo se encarga renderizar información nada de lógica compleja, eso hace que sea más fácil de mantener, tambien se puede conocer como Smart and dumb component.
Al final del dia es por buenas practicas de programacion, no podemos mezclar la logica de negocio con la informacion que solo queremos renderizar del componente.
Piensalo como si los componentes fueran fichas de Lego, no queremos mezclar todo con todo, es mejor tener piezas por separado, que cada una(en nuestro caso los componentes) 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.
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
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
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'},];
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!
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.
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í: