Comunicación entre componentes Angular

Intermedio
Angular
Angular
Actualizado: 27/08/2024

La comunicación entre componentes es esencial en las aplicaciones Angular para mantener la coherencia y la actualización de datos entre diferentes partes de la aplicación.

En Angular, existen varias técnicas para lograr esta comunicación entre componentes, y se pueden dividir en dos categorías principales: comunicación entre componentes relacionados y comunicación entre componentes no relacionados.

Comunicación entre componentes relacionados

Comunicación mediante propiedades (@Input())

Los componentes pueden intercambiar información pasando datos a través de propiedades, también conocido como "binding" en Angular.

Un componente puede enviar datos a otro componente utilizando la propiedad de entrada @Input().

Por ejemplo, supongamos que hay un componente UsuarioComponent que muestra detalles de un usuario:

// En UsuarioComponent
import { Component, Input } from '@angular/core';

@Component({
  selector: 'app-usuario',
  standalone: true,
  template: `
    @if (usuario) {
      <div>
        <h2>{{ usuario.nombre }}</h2>
        <p>{{ usuario.descripcion }}</p>
      </div>
    }
  `
})
export class UsuarioComponent {
  @Input() usuario?: Usuario;
}

Para usar este componente en otro componente, simplemente se enlaza la propiedad usuario:

@Component({
  selector: 'app-contenedor',
  standalone: true,
  imports: [UsuarioComponent],
  template: `
    <app-usuario [usuario]="usuarioActual" />
  `
})
export class ContenedorComponent {
  usuarioActual: Usuario = { nombre: 'Ana', descripcion: 'Desarrolladora' };
}

Comunicación mediante eventos (@Output())

Los componentes pueden comunicarse enviando eventos utilizando propiedades de salida.

Un componente emisor puede lanzar un evento utilizando la propiedad de salida @Output(), generalmente utilizando la clase EventEmitter, que puede ser escuchada por otro componente.

Por ejemplo, consideremos un componente ContadorComponent que permite al usuario aumentar un contador y notificar a otros componentes cuando cambia:

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

@Component({
  selector: 'app-contador',
  standalone: true,
  template: `
    <button (click)="aumentarContador()">Aumentar</button>
  `
})
export class ContadorComponent {
  contador = 0;
  @Output() cambioContador = new EventEmitter<number>();

  aumentarContador() {
    this.contador++;
    this.cambioContador.emit(this.contador);
  }
}

En el componente que utiliza ContadorComponent:

@Component({
  selector: 'app-contenedor',
  standalone: true,
  imports: [ContadorComponent],
  template: `
    <app-contador (cambioContador)="actualizarContador($event)" />
    <p>Contador actual: {{ contadorActual }}</p>
  `
})
export class ContenedorComponent {
  contadorActual = 0;

  actualizarContador(nuevoValor: number) {
    this.contadorActual = nuevoValor;
  }
}

Proyección de contenido

La proyección de contenido utiliza la etiqueta <ng-content> para insertar contenido dinámico en un componente desde su componente padre.

@Component({
  selector: 'app-mi-componente',
  standalone: true,
  template: `
    <div class="contenedor">
      <ng-content select="[header]"></ng-content>
      <ng-content select="[content]"></ng-content>
    </div>
  `
})
export class MiComponenteComponent {}

Uso en el componente padre:

@Component({
  selector: 'app-contenedor',
  standalone: true,
  imports: [MiComponenteComponent],
  template: `
    <app-mi-componente>
      <h3 header>Título personalizado</h3>
      <p content>Contenido personalizado</p>
    </app-mi-componente>
  `
})
export class ContenedorComponent {}

Comunicación entre componentes no relacionados

Servicios compartidos

Los servicios son instancias compartidas que permiten la comunicación entre componentes que no están directamente relacionados. 

La inyección de dependencias es el mecanismo mediante el cual se proporcionan estas instancias a los componentes que las necesitan.

Un servicio puede tener métodos para almacenar y recuperar datos, lo que facilita el intercambio de información entre componentes.

Por ejemplo, un UsuarioService podría proporcionar información de usuario a diferentes partes de la aplicación:

// En UsuarioService
import { Injectable, signal, computed } from '@angular/core';
import { Usuario } from './usuario.model';

@Injectable({
  providedIn: 'root'
})
export class UsuarioService {
 
 usuarioActual: Usuario; // Suponiendo que Usuario es una interfaz o clase

 constructor() {
     this.usuarioActual = {
         id: 1,
         nombre: 'Usuario Ejemplo',
         correo: 'usuario@example.com'
     };
 }

 actualizarUsuario(usuarioNuevo: Usuario) {
 this.usuarioActual = usuarioNuevo;
 }

 obtenerUsuario(): Usuario {
 return this.usuarioActual;
 }
}

Mediante la inyección de dependencias, un componente puede acceder al servicio en su constructor:

// En cualquier componente
import { Component } from '@angular/core';
import { UsuarioService } from './usuario.service'; // Importar el servicio

@Component({
 selector: 'app-mi-componente',
 templateUrl: './mi-componente.component.html',
 styleUrls: ['./mi-componente.component.css']
})
export class MiComponenteComponent {

 usuario: Usuario; // Suponiendo que Usuario es una interfaz o clase

 constructor(private usuarioService: UsuarioService) {
     // El servicio UsuarioService se inyecta en el constructor
     this.usuario = this.usuarioService.usuarioActual;
 }
}
Alan Sastre - Autor del tutorial

Alan Sastre

Ingeniero de Software y formador, CEO en CertiDevs

Ingeniero de software especializado en Full Stack y en Inteligencia Artificial. Como CEO de CertiDevs, Angular es una de sus áreas de expertise. Con más de 15 años programando, 6K seguidores en LinkedIn y experiencia como formador, Alan se dedica a crear contenido educativo de calidad para desarrolladores de todos los niveles.

Más tutoriales de Angular

Explora más contenido relacionado con Angular y continúa aprendiendo con nuestros tutoriales gratuitos.

Aprendizajes de esta lección

  1. Comprender la importancia de la comunicación entre componentes en Angular.
  2. Distinguir entre comunicación entre componentes relacionados y no relacionados.
  3. Dominar el uso de propiedades y eventos para comunicación entre componentes.
  4. Aprender a utilizar servicios compartidos para comunicación entre componentes.