Entendiendo @Input, @Output y EventEmitter en Angular

Para los que son nuevos en Angular, los decoradores Input y Output son un poco confusos, sobre todo cuando los estudias viendo código de ejemplo. En este artículo, intentaré explicarlos de la forma más sencilla.

Una herramienta para intercambiar datos

En primer lugar, la idea de Input y Output es intercambiar datos entre componentes. Son un mecanismo para enviar/recibir datos de un componente a otro.

Input se utiliza para recibir datos mientras que Output se utiliza para enviar datos. Output envía datos exponiendo productores de eventos, normalmente objetos EventEmitter.

Así que cuando veas código como este

@Component({
selector: 'todo-item',
...
})export class TodoItemComponent {
@Input() item
@Output() onChange = new EventEmitter()
}

eso significa

  • hey, estoy esperando que me envíen datos. Lo recibiré y lo almacenaré en mi propiedad item
  • por cierto, produciré y enviaré datos a través de la propiedad onChange.

Digamos que tienes un componente TodoList que contiene el componente TodoItem. En la plantilla de TodoList, se espera ver

...
<todo-item
="myTask"
(onChange)="handleChange($event)"
</todo-item>
...

lo que significa que

  • TodoList pone los valores de los datos en su propiedad myTask y los pasa a TodoItem
  • los datos emitidos desde TodoItem serán recibidos y manejados por la función handleChange() en TodoList

Eso es todo para la teoría. Veamos el ejemplo.

@Input y @Output en acción

Mira este ejemplo. Aquí he creado 2 componentes, el componente hello anidado dentro del componente app. El componente hello tiene un Input y un Output

hello.component.ts
@Component({
selector: 'hello',
template: `
<h3 (click)="onClick.emit('Neo')">
...
</h3>
`
})export class HelloComponent {
@Input() myFriend: string
@Output() onClick = new EventEmitter()
}

Espera recibir un valor de cadena y lo almacena en la propiedad myFriend.

@Input() myFriend: string

Cada vez que hagas clic en él, la propiedad Output onClick emitirá una cadena ‘Neo’ al mundo exterior.

<h3 (click)="onClick.emit('Neo')">

Abajo está el componente de la app

app.component.ts
export class AppComponent {
ng = 'Angular'
myName = 'Neo' upCase(st:string): void { ... }
}app.component.html
<hello myFriend="{{ ng }}" (onClick)="upCase($event)"></hello>
<h3>My name is {{ myName }}</h3>

Nota que el componente de la app usa la etiqueta hello en su plantilla y hace dos cosas:

  • pasar un valor de cadena ‘Angular’ a hello a través de su propiedad ng
<hello myFriend="{{ ng }}"
  • recibir el valor emitido de hello y procesar ese valor mediante la función upCase()
<hello myFriend="{{ ng }}" (onClick)="upCase($event)">

Puedes ver la app en acción aquí