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 @Inputy@Outputpara 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 @ViewChildy@ViewChildrenpara 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 @Outputpara 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: `
    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