Saltar al contenido

Cómo Pasar Datos Entre 2 Componentes Hijos en Angular

Cómo Pasar Datos Entre 2 Componentes Hijos en Angular

En Angular, la comunicación entre componentes es una parte fundamental cuando desarrollamos aplicaciones complejas. En este artículo, aprenderás cómo pasar datos entre dos componentes hijos utilizando diferentes técnicas, desde las más comunes hasta una más avanzada utilizando un servicio de tipo Event Bus.

Vamos a revisar las siguientes opciones:

  1. Usar @Input() y @Output() para pasar datos directamente entre los componentes hijos y padres.
  2. Usar un servicio compartido para una comunicación más flexible y global.
  3. Usar un Event Bus para manejar eventos de forma desacoplada y centralizada.

Cada una de estas soluciones tiene su propio uso y propósito, por lo que es importante entender cuándo y cómo usar cada una.

1. Usando @Input() y @Output()

La forma más directa de pasar datos entre componentes en Angular es usando las propiedades @Input() y @Output(). Aquí, 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 actúa 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: Comunicación a través 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 botón en ChildB es presionado, ChildA recibirá los datos a través del componente padre.

Ventajas y Desventajas de @Input y @Output

  • Ventajas: Simples de implementar y usar para componentes que tienen una relación jerárquica clara (padre-hijo).
  • Desventajas: Cuando se requiere pasar datos entre componentes sin una relación directa de padre-hijo, esta solución no es la más adecuada.

2. Usar un Servicio Compartido con BehaviorSubject

Una alternativa más flexible a @Input y @Output es usar un servicio compartido. Esto permite la comunicación entre componentes que no tienen una relación directa de padre-hijo.

Paso 1: Crear un Servicio

Vamos a crear un servicio con un BehaviorSubject que mantendrá el estado y permitirá la comunicación 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 comunicación directa entre componentes sin importar la estructura jerárquica.
  • Desventajas: Puede ser excesivo para comunicaciones simples entre componentes con relaciones de padre-hijo.

3. Usar un Event Bus (Advanced)

Un patrón más avanzado para manejar la comunicación entre componentes es utilizar un Event Bus. Este patrón es útil cuando se necesita una comunicación más desacoplada entre varios componentes.

Paso 1: Crear un Event Bus Service

El Event Bus es esencialmente un servicio que maneja eventos a través 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 más grandes con múltiples interacciones.
  • Desventajas: Puede ser excesivo para aplicaciones pequeñas y introduce un nuevo nivel de complejidad.

Conclusión

En este artículo, exploramos diferentes maneras de pasar datos entre dos componentes hijos en Angular. Usar @Input() y @Output() es una solución sencilla cuando los componentes tienen una relación directa de padre-hijo, mientras que los servicios compartidos y el patrón Event Bus proporcionan opciones más avanzadas y flexibles para aplicaciones más grandes y con una estructura de componentes más compleja.

Escoge la solución que mejor se adapte a tu caso y necesidades de tu aplicación. ¡Happy coding!

Picture of Yeison Lapaix
Yeison Lapaix
Hola!, Soy Yeison Lapaix un desarrollador Full Stack .Net con más de 10 años de experiencia en el desarrollo de aplicaciones web con ASP.NET Core, MVC, C#, JavaScript, Oracle DB y SQL Server. Tengo buena experiencia en la creación de API web RESTful con .Net Core y aplicaciones front-end con Angular, Vue JS, jQuery, HTML5 y CSS. Trabajo competente con principios OOP y patrones de diseño, principios SOLID y experiencia con entornos de desarrollo ágiles. Me considero un desarrollador entusiasta que busca mejoras continuas para ser mejor cada día.

TABLE OF CONTENTS

Yeison Lapaix – Full Stack Developer | .NET | Angular | Systems Engineer | Technology Enthusiast