No tienes acceso a esta clase

隆Contin煤a aprendiendo! 脷nete y comienza a potenciar tu carrera

Uso de Outputs

4/20
Recursos

As铆 como el decorador @Input permite el env铆o de informaci贸n desde un componente padre hacia un componente hijo, el uso de @Outputs permite lo contrario.

Comunicaci贸n hijo a padre

A partir de la emisi贸n de un evento, el decorador @Output() permite enviar mensajes desde un componente hijo hacia el padre.

uso de outputs.png

Env铆o del mensaje

Para esto, se hace uso de la clase EventEmitter import谩ndola desde @angular/core, para crear en tu componente una propiedad emisora de eventos.

import { Component, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-test-name',
  templateUrl: './test-name.component.html',
  styleUrls: ['./test-name.component.less']
})
export class TestNameComponent {

  @Output() message = new EventEmitter<string>();

  constructor() { }
}

Decorando la propiedad con el @Output() y creando una instancia de EventEmitter podr谩s emitir un evento de la siguiente manera:

    ...
    emitirEvento() {
        this.message.emit('Hola soy Platzi');
    }

Llamando al m茅todo emit() de la instancia EventEmitter, se enviar谩 el valor al componente padre que se encuentre escuchando el evento.

Recepci贸n del mensaje

Desde el componente padre, inicializa el componente hijo de la siguiente manera:

<app-test-name>
    (message)="recibirMensaje($event)"
</app-test-name>

Se 鈥渂indea鈥 la propiedad emisora de eventos con () y se le pasa una funci贸n que se ejecutar谩 cada vez que emita un evento.
Y en el componente padre:

import { Component } from '@angular/core';

@Component({
  selector: 'app-father',
  templateUrl: './father.component.html',
  styleUrls: ['./father.component.less']
})
export class FatherComponent {

  constructor() { }
  
  recibirMensaje(event: Event) {
    console.log(event);
  }
}

La funci贸n recibirMensaje() posee un par谩metro del tipo Event que contendr谩 el mensaje del componente hijo.


Contribuci贸n creada con los aportes de Kevin Fiorentino.

Aportes 20

Preguntas 13

Ordenar por:

驴Quieres ver m谩s aportes, preguntas y respuestas de la comunidad?

o inicia sesi贸n.

Con el evento de error ya no es necesario poner ng-template pues si detecta el evento del error se lanza el metodo de imgError() y se carga la imageDefault

El decorador @Output nos permite enviar informaci贸n desde el componente hijo en direcci贸n al componente padre por medio de un Event Emitter, para declarar un output lo hacemos de la siguiente manera:

@Output miOutput = new EventEmitter();

Si ademas queremos tipear este output para ser mas especificos con la informaci贸n que vamos a enviar entonces declaramos:

@Output miOutput = new EventEmitter<string>();

Lo siguiente es emitir esa informaci贸n desde el componente hijo por medio de la funci贸n emit() de nuestro EventEmitter declarado, en este caso 鈥榤iOutput鈥 por lo cual emitimos la informaci贸n de la forma siguiente:

this.miOutput.emit('mi string proveniente desde componente hijo')

Para recibir esa informaci贸n desde el componente padre utilizamos el event binding dentro del tag del componente hijo y hacemos referencia al nombre del event emitter del componente hijo, ejemplo:

<componente-hijo (miOutput)="funcionQueRecibeElOutput($event)" ></componente-hijo>

En el componente padre tendremos que recibir la informaci贸n por medio de una funci贸n, en este caso es funcionQueRecibeElOutput($event) donde 鈥$event鈥 es la informaci贸n que emite el componente hijo, y esta funci贸n se encargara de procesar la informaci贸n que le llegue desde el event emitter

Aqui hay una imagen default

https://www.m2crowd.com/core/i/placeholder.png

La proxima vez, si tan solo pudieras llamar de la misma manera a los componenrtes no seria tan complejo. Me explico, en el 7:54 dices 鈥渘uestro componente鈥 y se me explot贸 el cerebro, si solo dices el componente hijo ser铆a genial. Puede que el aporte sea muy idiota, pero para los que estamos aprendiendo es muy valioso esos peque帽os detalles entre tantas ventanas.
Estoy muy contento con el curso, usted explica muy bien.

Creo que lo explico de forma muy complicada sobre todo con eso de strings e imagenes, lo que hizo es esto:

Para pasar informaci贸n al padre necesitamos dos modulos Output y EventEmitter, lo haremos a traves de un evento creado por nosotros imgLoaded:
import { Component, OnInit, Input, Output, EventEmitter } from 鈥楡angular/core鈥;
@Output() loaded = new EventEmitter<string>();
imgLoaded(){
console.log(鈥榣og hijo鈥)
this.loaded.emit(鈥榚jemplo string del hijo a padre鈥);
}
Fijate como usa this.loaded.emit eso es lo que vamos a pasar del hijo al padre
Aqui lo usamos, loaded es un evento nativo de img:
<img width=鈥200鈥 (load)=鈥渋mgLoaded()鈥 (error)=鈥渋mgError()鈥 [src]=鈥渋mg鈥 *ngIf=鈥渋mg; else elseImg鈥>
En el componente padre lo recibimos:
<app-img (loaded)=鈥渙nLoaded($event)鈥 [img]=鈥渋mgParent鈥></app-img>
Ese evento loaded tambien es nativo de img, por convencion se utiliza $ para eventos:
onLoaded(img: string){
console.log(鈥榣og padre鈥, img)
}

鈥 OUTPUTS 鈥

//Importar
import { Output, EventEmitter } from 鈥楡angular/core鈥;

//Crear evento
@Output() loaded = new EventEmitter();

imgLoaded() {
console.log(鈥榣oaded鈥);
//Activar evento
this.loaded.emit();
}

Pasar informaci贸n del hijo al padre.

Uso de Outputs

Los outputs son para pasarle informaci贸n del hijo al padre.

En el hijo, img.components.ts:

import { Component, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-img',
  templateUrl: './img.component.html',
  styleUrls: ['./img.component.scss']
})
export class ImgComponent {
  @Input() img: string = ''; //* se comunica con el hijo

  @Output() loaded = new EventEmitter<string>(); //* se comunica con el padre

  imageDefault = './assets/images/default.png'

  imgError() {
    this.img = this.imageDefault;
  }

  imgLoaded() {
    console.log('log hijo!');
    this.loaded.emit(this.img); //* notificando al padre
  }
}

con su html img.component.html:

<img
  [src]="img"
  alt="imagen chida"
  width="200"
  *ngIf="img; else elseImg"
  (error)="imgError()"
  (load)="imgLoaded()"
>
<ng-template #elseImg>
  <img [src]="imageDefault" alt="default">
</ng-template>

Recibimos la informaci贸n y notificaci贸n en el padre, app.component.ts:

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent {
  imgParent = '';

  onLoaded(img: string) {
    console.log('log padre!', img); //* img viene del hijo
  }
}

y su html, app.component.html:

<input type="text" [(ngModel)]="imgParent">

<app-img (loaded)="onLoaded($event)" [img]="imgParent"></app-img>

muy bueno el evento (error), me ser谩 muy 煤til de ahora en m谩s 馃挭馃徑

Tambien existe la forma de pasar informacion desde el componente hijo hacia el componente padre mediante el uso de el decorador @Output y el EventEmitter.

  • @Output: Es un decorador que nos permite pasar datos entre componentes.
  • EventEmitter: Es un m贸dulo que ayuda a compartir datos entre componentes usando los m茅todos emit() y subscribe(). EventEmitter est谩 en la capa Observables, que observa cambios y valores y emite los datos a los componentes suscritos a esa instancia de EventEmitter.

Para emitir un valor desde el componente hijo que pueda ser escuchado por el componente padre utilizamos el decorador @Output con un EventEmitter que nos va a permitir crear un evento personalizado el cual podremos escuchar desde nuestro componente padre.

c贸mo pasa el m谩s de una event o variable?

para usar @Output = transmitir informaci贸n del hijo al padre:

primero en el TS del hijo, se importa Output y EventEmitter,
se crea una variable de tipo EventEmmiter<TipoDato>() con decorador Output, en el componente HTML del hijo se adiciona la funcionalidad (load) haciendo referencia a la funci贸n que va a realizar el emit.
Por ultimo en el TS del componente hijo se crea la funci贸n que va por medio de la variable creada anteriormente a realizar un evento emit(dato a transmitir).

En el componente HTML del padre donde se esta mostrando el HTML del hijo <app-img (loaded)=鈥渙nLoaded($event)鈥 [img]=鈥渋mgPadre鈥></app-img> se adiciona la funcionalidad (loaded) en el cual va a ejecutar una funci贸n que para obtener la informaci贸n del componente hijo se realiza por medio de un $event.
En el componente TS del padre se hace la funci贸n en este caso onLoaded(img:string) en la cual recibe por par谩metro la informaci贸n y listo puede usarla.

De esta manera logre enviarle al padre las im谩genes que se cargaron correctamente y informaci贸n en caso de que la imagen no se haya cargado correctamente

@Input() src = '';
@Output() loaded = new EventEmitter<object | string>();

imageDefault =
  'https://c8.alamy.com/compes/2h1ywt1/producto-defectuoso-resumen-concepto-vector-ilustracion-2h1ywt1.jpg';

imageError = {
  isError: false,
  src: this.src,
};

errorImage() {
  this.imageError.isError = !this.imageError.isError;
  this.imageError.src = this.src;
  this.src = this.imageDefault;
}

imageLoaded() {
  if (this.imageError.isError)
    return this.loaded.emit({
      message: 'there is an error uploading an image',
      error: this.imageError.src,
    });
  this.loaded.emit(this.src);
}

me perdi con tanta vuelta en padre eh hijo deberia ser mas practico, no entiendo ayuda

Esto fue algo de lo que implement茅 en mi proyecto de tienda, espero que sea de ayuda para todos.

/*
En este caso, tenemos un componente que registra unos productos seleccionados en 
un array de datos seleccionados, lo que se desea es que el componente emita el valor 
total para todos los productos seleccionados al componente padre.
*/
import { Component, OnInit, Output, EventEmitter } from '@angular/core';
import { Product } from 'app/shared/product-list/product.model';
import { ProductSelectionService } from 'app/shared/product-list/product-selection.service';

@Component({
  selector: 'app-products-basket',
  templateUrl: './products-basket.component.html',
  styleUrls: ['./products-basket.component.scss']
})
export class ProductsBasketComponent implements OnInit {

  selectedProducts: Product[] = [];
	/*
	   Creamos la propiedad con la que se va a emitir el valor total de la canasta
   */
  @Output() totalofBasket: EventEmitter<number> = new EventEmitter<number>();

  constructor(private productSelectionService: ProductSelectionService) {}

  ngOnInit() {
	 /*
	   Al iniciar el componente, se van a traer los productos seleccionados
     a trav茅s del servicio.
   */
    this.selectedProducts = this.productSelectionService.getSelectedProducts();
		/*
	    Posteriormente emitir el valor total al iniciar el componente.
    */
    this.emitTotalValue();
  }

  emitTotalValue() {
		/*
	    Aqu铆 se va a emitir el valor total despu茅s de ser calculado
    */
    const totalValue = this.calculateTotalValue();
    this.totalofBasket.emit(totalValue);
  }

  private calculateTotalValue(): number {
		/*
	    Aqu铆 se calcula el valor total de los productos seleccionados,
			cabe mencionar que esta funci贸n es privada para este componente 
			y esta retornando un valor de tipo numero 
    */
    return this.selectedProducts.reduce((total, product) => total + product.price, 0);
	  /*
	    Se calcula seleccionado el precio en la informaci贸n de cada producto y solamente}
			se suman uno a uno
    */
	}

}
<!--
En el componente padre al llamar <app-products-basket> o el componente hijo,
hacemos el llamado de la propiedad con valor de la funci贸n que va recibir
el evento como parametro a trav茅s de $event
-->
<section class="cart">
   <app-products-basket (totalofBasket)="totalBasket($event)"></app-products-basket>
</section>
/*
En el .ts del componente padre simplemente se recibe este valor y se 
manipula seg煤n las necesidades
*/

import { Component } from '@angular/core';

@Component({
  selector: 'app-cart',
  templateUrl: './cart.component.html',
  styleUrls: ['./cart.component.scss']
})
export class CartComponent {
  totalPrice: number = 0;

  totalBasket(value: number) {
    console.log('El total es de', value);
    this.totalPrice = value;
  }
}

Quiero compartirles que los OutPut pueden tener un nombre personalizado para ser invocados con el EventBinding, de esta forma puedes usar un nombre distinto al nombre de la propiedad que tiene el decorador @Output. ejemplo:

@Output('loaded')
public imgLoaded: EventEmitter<string> = new EventEmitter<string>();

Dentro de los par茅ntesis y en comillas simples, se puede escribir el nombre con el que se estar谩 escuchando el evento que emite el componente hijo. De esta forma aunque la propiedad se llame 鈥渋mgLoaded鈥 en el componente padre se va a escuchar por medio de 鈥渓oaded鈥.

<app-img (loaded)="onLoaded()" [img]="imgParent"></app-img>

En Angular, los outputs son eventos que se emiten desde un componente hijo hacia su componente padre. Los outputs se utilizan para notificar al componente padre sobre cambios o acciones realizadas en el componente hijo. Los outputs se declaran en el decorador @Output() del componente hijo y se utilizan en conjunto con los eventos de la plantilla para emitir eventos hacia el componente padre. Los componentes padres pueden escuchar estos eventos y ejecutar acciones en respuesta a ellos, permitiendo una comunicaci贸n bidireccional entre los componentes.

Uso de Outputs

En Angular, los @Output() son una forma de comunicaci贸n unidireccional, donde el componente hijo emite un evento y el componente padre lo escucha y reacciona a 茅l.

<aside>
<img src=鈥https://static.platzi.com/media/achievements/badge-angular-componentes-servicios-75f68ec3-48e0-430e-b7e2-889fad0d1984.png鈥 alt=鈥https://static.platzi.com/media/achievements/badge-angular-componentes-servicios-75f68ec3-48e0-430e-b7e2-889fad0d1984.png鈥 width=鈥40px鈥 /> Esto se usa com煤nmente para comunicarse desde un componente hijo a su componente padre.

</aside>

Para usar @Output(), se debe declarar una propiedad de evento en el componente hijo con el decorador @Output().

  • componente-hijo.component.ts
import { Component, EventEmitter, Output } from '@angular/core';

@Component({
  selector: 'app-componente-hijo',
  template: `
    <button (click)="eliminar()">Eliminar</button>
  `
})
export class ComponenteHijoComponent {
  @Output() eliminado = new EventEmitter();

  eliminar() {
    this.eliminado.emit();
  }
}

En este ejemplo, se define una propiedad de evento eliminado con el decorador @Output(). Luego, dentro del m茅todo eliminar(), se emite este evento llamando al m茅todo emit() en la propiedad de evento.

  • componente-padre.component.html
<app-componente-hijo (eliminado)="onEliminar()"></app-componente-hijo>

En el componente padre, se utiliza la directiva (eliminado)="onEliminar()" para escuchar el evento eliminado emitido por el componente hijo. En este ejemplo, la funci贸n onEliminar() se ejecutar谩 cada vez que se haga clic en el bot贸n 鈥淓liminar鈥 en el componente hijo.

  • componente-padre.component.ts
import { Component } from '@angular/core';

@Component({
  selector: 'app-componente-padre',
  template: `
    <app-componente-hijo (eliminado)="onEliminar()"></app-componente-hijo>
  `
})
export class ComponentePadreComponent {
  onEliminar() {
    console.log('El componente hijo emiti贸 el evento de eliminaci贸n');
  }
}

Con tanto img por aqu铆 y por all谩 me cuesta much铆simo seguir la clase, tanto nombrar que si componente padre/hijo y dar vueltas para un lado y para otro me pierdo todo el rato. Me da la sensaci贸n que estar铆a mucho mejor si solo se explicara de primeras qu茅 hace Input y Output y nos explicaran con un ejemplo un poco m谩s realista sin tanto rodeo.