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
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
- Comprender la importancia de la comunicación entre componentes en Angular.
- Distinguir entre comunicación entre componentes relacionados y no relacionados.
- Dominar el uso de propiedades y eventos para comunicación entre componentes.
- Aprender a utilizar servicios compartidos para comunicación entre componentes.