Comunicación entre componentes en Angular
La comunicación entre componentes en Angular es esencial para la creación de aplicaciones complejas y estructuradas. Permite a los componentes compartir datos y responder a eventos entre ellos. Esto se puede lograr de varias maneras:
- Input/Output Binding: Uso de decoradores
@Input
y@Output
para pasar datos y emitir eventos entre componentes padre e hijo. - Servicios: Uso de servicios para compartir datos y lógica entre componentes que no están directamente relacionados.
- Template Reference Variables: Uso de variables de referencia en plantillas para interactuar directamente con componentes hijo.
- ViewChild/ViewChildren: Uso de decoradores
@ViewChild
y@ViewChildren
para acceder a instancias de componentes hijo desde el componente padre.
- https://angular.dev/tutorials/learn-angular/8-input#
- https://angular.dev/tutorials/learn-angular/9-output#
- https://angular.dev/guide/components/queries#view-queries
Componentes de Comunicación Entre Componentes en Angular v18
- @Input: Decorador que permite que un componente reciba datos de un componente padre.
- @Output: Decorador que permite que un componente emita eventos hacia un componente padre.
- EventEmitter: Clase utilizada junto con
@Output
para emitir eventos. - Servicios: Clases inyectables que pueden ser compartidas entre componentes para mantener y gestionar estados o lógica de negocio.
- Template Reference Variables: Variables definidas en la plantilla para referenciar componentes o elementos DOM.
- @ViewChild: Decorador que permite acceder a un solo elemento hijo en el DOM.
- @ViewChildren: Decorador que permite acceder a múltiples elementos hijos en el DOM.
Videotutorial:
- Curso Angular 2023 #6 Comunicacion Entre Componentes En Angular: https://youtu.be/m5vQDATqqiY?list=PLxjAmQnB-4D-zYOs2sT68_6btSZ1Vuzj4
- Filtro dinámico - Comunicación entre componentes I: https://youtu.be/r_6eqIOGpDM?list=PLysCxvRbcLqA3BnWfkzH7lVeIMn5uNx8c
- Filtro dinámico - Comunicación entre componentes II: https://youtu.be/hKrSgro318I?list=PLysCxvRbcLqA3BnWfkzH7lVeIMn5uNx8c
- Filtro dinámico - Comunicación entre componentes III: https://youtu.be/_VWefW3ZT8Q
- ..
@Input:
- Se usa para recibir datos de un componente padre.
import { Component, Input } from '@angular/core';
@Component({
selector: 'child-component',
template: `{{ data }}
`
})
export class ChildComponent {
@Input() data: string;
}
@Output:
- Se usa para emitir eventos a un componente padre.
import { Component, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `<button (click)="sendData()">Send Data</button>`
})
export class ChildComponent {
@Output() dataEmitter = new EventEmitter<string>();
sendData() {
this.dataEmitter.emit('Hello from Child');
}
}
</string>
EventEmitter
EventEmitter: Clase utilizada para emitir eventos personalizados. Se usa junto con @Output.
import { EventEmitter } from '@angular/core';
this.dataEmitter = new EventEmitter<string>();
Servicios
Servicios: Clases que contienen lógica y datos compartidos entre componentes.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
private data: string;
setData(data: string) {
this.data = data;
}
getData(): string {
return this.data;
}
}
Servicios
Servicios: Clases que contienen lógica y datos compartidos entre componentes.
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
private data: string;
setData(data: string) {
this.data = data;
}
getData(): string {
return this.data;
}
}
Template Reference Variables
Template Reference Variables: Se usan en las plantillas para referenciar elementos DOM o componentes.
<child-component #child></child-component>
<button (click)="child.sendData()">Trigger Child Method</button>
@ViewChild:
- Se usa para acceder a un componente hijo desde el componente padre.
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'parent-component',
template: `
`
})
export class ParentComponent {
@ViewChild(ChildComponent) childComponent: ChildComponent;
ngAfterViewInit() {
this.childComponent.sendData();
}
}
mm
import { Component, ViewChildren, QueryList } from '@angular/core';
import { ChildComponent } from './child.component';
@Component({
selector: 'parent-component',
template: `
<child-component></child-component>
<child-component></child-component>
`
})
export class ParentComponent {
@ViewChildren(ChildComponent) children: QueryList<ChildComponent>;
ngAfterViewInit() {
this.children.forEach(child => child.sendData());
}
}
Ejemplo de Comunicación Entre Componentes
Este ejemplo muestra cómo los componentes pueden comunicarse entre sí usando @Input
, @Output
, EventEmitter
, y un servicio compartido. Los datos pueden fluir del componente padre al componente hijo a través de @Input
y en la dirección opuesta a través de @Output
y EventEmitter
. Además, un servicio puede mantener y proporcionar datos compartidos a través de múltiples componentes.
Configuración del módulo:
// app.module.ts
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { AppComponent } from './app.component';
import { ParentComponent } from './parent.component';
import { ChildComponent } from './child.component';
@NgModule({
declarations: [AppComponent, ParentComponent, ChildComponent],
imports: [BrowserModule],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
Servicio de datos compartidos:
// data.service.ts
import { Injectable } from '@angular/core';
@Injectable({
providedIn: 'root'
})
export class DataService {
private data: string;
setData(data: string) {
this.data = data;
}
getData(): string {
return this.data;
}
}
Componente Hijo:
// child.component.ts
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'child-component',
template: `
<div>
<p>Data from parent: {{ data }}</p>
<button (click)="sendData()">Send Data to Parent</button>
</div>
`
})
export class ChildComponent {
@Input() data: string;
@Output() dataEmitter = new EventEmitter<string>();
sendData() {
this.dataEmitter.emit('Data from Child');
}
}
</string>
Componente Padre:
// parent.component.ts
import { Component, ViewChild } from '@angular/core';
import { ChildComponent } from './child.component';
import { DataService } from './data.service';
@Component({
selector: 'parent-component',
template: `
<div>
<h2>Parent Component</h2>
<button (click)="sendDataToChild()">Send Data to Child</button>
<child-component [data]="parentData" (dataEmitter)="receiveData($event)"></child-component>
</div>
`
})
export class ParentComponent {
parentData: string = 'Data from Parent';
@ViewChild(ChildComponent) childComponent: ChildComponent;
constructor(private dataService: DataService) {}
sendDataToChild() {
this.dataService.setData('Updated Data from Parent');
this.childComponent.data = this.dataService.getData();
}
receiveData(data: string) {
console.log('Received data from child:', data);
}
}
Componente Principal:
// app.component.ts
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
template: `
<div>
<h1>Angular Communication Example</h1>
<parent-component></parent-component>
</div>
`
})
export class AppComponent {}
mm