Como Pasar Datos Entre 2 Componentes Hijos en Angular

En Angular, la comunicacion entre componentes es una parte fundamental cuando desarrollamos aplicaciones complejas. En este articulo, aprenderas como pasar datos entre dos componentes hijos utilizando diferentes tecnicas, desde las mas comunes hasta una mas avanzada utilizando un servicio de tipo Event Bus.
Vamos a revisar las siguientes opciones:
- Usar @Input() y @Output() para pasar datos directamente entre los componentes hijos y padres.
- Usar un servicio compartido para una comunicacion mas flexible y global.
- Usar un Event Bus para manejar eventos de forma desacoplada y centralizada.
Cada una de estas soluciones tiene su propio uso y proposito, por lo que es importante entender cuando y como usar cada una.
1. Usando @Input() y @Output()
La forma mas directa de pasar datos entre componentes en Angular es usando las propiedades @Input() y @Output(). Aqui, uno de los componentes hijos recibe datos del componente padre mediante @Input(), mientras que el otro componente hijo puede emitir eventos al padre usando @Output(). El padre actua como intermediario.
Paso 1: Crear los Componentes Hijos
Primero, necesitamos dos componentes hijos: ChildA y ChildB.
ng generate component child-a
ng generate component child-b
Paso 2: Pasar Datos con @Input
En el componente ChildA, usaremos @Input() para recibir datos.
// child-a.component.ts
import { Component, Input } from '@angular/core';
@Component({
selector: 'app-child-a',
template: `<h3>Child A</h3>
<p>Data received: {{ data }}</p>`
})
export class ChildAComponent {
@Input() data: string = '';
}
Paso 3: Emitir Eventos con @Output
En el componente ChildB, usamos @Output() para emitir eventos con datos hacia el componente padre.
// child-b.component.ts
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-child-b',
template: `<h3>Child B</h3>
<button (click)=\"sendData()\">Send Data to Parent</button>`
})
export class ChildBComponent {
@Output() dataEvent = new EventEmitter<string>();
sendData() {
this.dataEvent.emit('Hello from Child B');
}
}
Paso 4: Comunicacion a traves del Componente Padre
El componente padre recibe los datos de ChildB y los pasa a ChildA.
// parent.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-parent',
template: `
<app-child-a [data]=\"childBData\"></app-child-a>
<app-child-b (dataEvent)=\"receiveData($event)\"></app-child-b>
`
})
export class ParentComponent {
childBData: string = '';
receiveData(data: string) {
this.childBData = data;
}
}
Ahora, cuando el boton en ChildB es presionado, ChildA recibira los datos a traves del componente padre.
Ventajas y Desventajas de @Input y @Output
- Ventajas: Simples de implementar y usar para componentes que tienen una relacion jerarquica clara (padre-hijo).
- Desventajas: Cuando se requiere pasar datos entre componentes sin una relacion directa de padre-hijo, esta solucion no es la mas adecuada.
2. Usar un Servicio Compartido con BehaviorSubject
Una alternativa mas flexible a @Input y @Output es usar un servicio compartido. Esto permite la comunicacion entre componentes que no tienen una relacion directa de padre-hijo.
Paso 1: Crear un Servicio
Vamos a crear un servicio con un BehaviorSubject que mantendra el estado y permitira la comunicacion entre los componentes.
ng generate service data
// data.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class DataService {
private dataSource = new BehaviorSubject<string>('Default Data');
currentData = this.dataSource.asObservable();
changeData(data: string) {
this.dataSource.next(data);
}
}
Paso 2: Actualizar ChildA para Recibir Datos del Servicio
// child-a.component.ts
import { Component, OnInit } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-child-a',
template: `<h3>Child A</h3>
<p>Data from service: {{ data }}</p>`
})
export class ChildAComponent implements OnInit {
data: string = '';
constructor(private dataService: DataService) {}
ngOnInit() {
this.dataService.currentData.subscribe(data => this.data = data);
}
}
Paso 3: Actualizar ChildB para Enviar Datos al Servicio
// child-b.component.ts
import { Component } from '@angular/core';
import { DataService } from '../data.service';
@Component({
selector: 'app-child-b',
template: `<h3>Child B</h3>
<button (click)=\"sendData()\">Send Data via Service</button>`
})
export class ChildBComponent {
constructor(private dataService: DataService) {}
sendData() {
this.dataService.changeData('Hello from Child B');
}
}
Ventajas y Desventajas de Usar un Servicio Compartido
- Ventajas: Permite una comunicacion directa entre componentes sin importar la estructura jerarquica.
- Desventajas: Puede ser excesivo para comunicaciones simples entre componentes con relaciones de padre-hijo.
3. Usar un Event Bus (Avanzado)
Un patron mas avanzado para manejar la comunicacion entre componentes es utilizar un Event Bus. Este patron es util cuando se necesita una comunicacion mas desacoplada entre varios componentes.
Paso 1: Crear un Event Bus Service
El Event Bus es esencialmente un servicio que maneja eventos a traves de observables.
// event-bus.service.ts
import { Injectable } from '@angular/core';
import { Subject } from 'rxjs';
@Injectable({
providedIn: 'root',
})
export class EventBusService {
private eventBus = new Subject<{ name: string, data: any }>();
on(event: string) {
return this.eventBus.asObservable();
}
emit(event: string, data: any) {
this.eventBus.next({ name: event, data });
}
}
Paso 2: Actualizar ChildA para Escuchar Eventos del Event Bus
// child-a.component.ts
import { Component, OnInit } from '@angular/core';
import { EventBusService } from '../event-bus.service';
@Component({
selector: 'app-child-a',
template: `<h3>Child A</h3>
<p>Event Data: {{ data }}</p>`
})
export class ChildAComponent implements OnInit {
data: string = '';
constructor(private eventBus: EventBusService) {}
ngOnInit() {
this.eventBus.on('dataEvent').subscribe(event => this.data = event.data);
}
}
Paso 3: Actualizar ChildB para Emitir Eventos al Event Bus
// child-b.component.ts
import { Component } from '@angular/core';
import { EventBusService } from '../event-bus.service';
@Component({
selector: 'app-child-b',
template: `<h3>Child B</h3>
<button (click)=\"sendEvent()\">Send Event</button>`
})
export class ChildBComponent {
constructor(private eventBus: EventBusService) {}
sendEvent() {
this.eventBus.emit('dataEvent', 'Hello from Child B');
}
}
Ventajas y Desventajas de Usar un Event Bus
- Ventajas: Desacopla completamente los componentes y es ideal para aplicaciones mas grandes con multiples interacciones.
- Desventajas: Puede ser excesivo para aplicaciones pequenas e introduce un nuevo nivel de complejidad.
Conclusion
En este articulo, exploramos diferentes maneras de pasar datos entre dos componentes hijos en Angular. Usar @Input() y @Output() es una solucion sencilla cuando los componentes tienen una relacion directa de padre-hijo, mientras que los servicios compartidos y el patron Event Bus proporcionan opciones mas avanzadas y flexibles para aplicaciones mas grandes y con una estructura de componentes mas compleja.
Escoge la solucion que mejor se adapte a tu caso y necesidades de tu aplicacion. Happy coding!


