Cómo comunicar dos componentes sin relación en Angular

¿Necesitas pasar información entre 2 componentes que no tienen relación en Angular?, checa este tutorial y aprende cómo de forma fácil.

En Angular existen distintas formas de comunicarse entre componentes, entre ellas están:

Componente padre -> Componente hijo, esto a través de @Input y la directiva asignada.

Componente hijo -> Componente padre, esto a través de @ViewChild .

Pero, en esta ocasión veremos el tercer caso, cuando dos componentes no tienen relación alguna. ¿Cuándo pasa esto?, bueno, en ocasiones necesitan conectar dos componentes que no tienen relación directa, por ejemplo tienen un componente que es un carrito que se encuentra en su menú superior.

Como podremos ver, el carrito se encuentra en el Header, lo que podría ser, es un componente hijo del Header, sin embargo en este ejemplo tendremos un Componente que está fuera del Header, que supongamos es una tarjeta de un producto y queremos que, cuando le demos clic en comprar se comunique con el carrito y le diga que se tiene un producto ahora.

En este caso es donde entra la relación de poder comunicar un componente no relacionado con otro por ejemplo.

Para este tutorial lo veremos a través de texto, es decir, tendremos un mensaje y a este mensaje lo vamos a actualizar desde un componente y se actualizará a su componente secundario.

Antes de empezar, solo aclaro que en esta ocasión no pondré comentarios internos en los códigos como ya es costumbre que lo haga, porque este tutorial lo estoy haciendo un poco rápido así que por eso no los incluí.

Lo primero entonces es que haremos nuestro intermediario, en este caso le llamaremos HelperService ya que será un servicio que estará vinculado a ambos:

import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs';
@Injectable()
export class HelperService {
  private message = new BehaviorSubject<string>('En espera de un nombre');
  public customMessage = this.message.asObservable();
  constructor() {}
  public changeMessage(msg: string): void {
    this.message.next(msg);
  }
}

¿Qué pasa aquí?. Primero que nada el constructor no es totalmente necesario pero lo dejo de igual forma.

Ahora bien, lo primero es crear un BehaviorSubject desde RxJS, y después lo pasamos a una nueva variable comoObservable. En una analogía pensemos que hay 3 personas: A, B y C, en este caso B es este servicio (el observador), A y C son nuestros componentes, B observa a la persona A, cuando la persona A realiza una acción, le avisa a la persona C que la persona A realizó esa acción y entonces la persona C también la realiza, esto a través de la variable observable ( message ).

Aquí encuentran más información:

https://rxjs-dev.firebaseapp.com/api/index/class/BehaviorSubject

Posteriormente, creamos una función para que podamos cambiar el mensaje a cualquiera a través de un ngModel más adelante.

Y eso es todo, así de simple. Guardamos como helper.service.ts y en nuestro app.module.ts lo incluimos dentro de los providers y en el import superior:

import { HelperService } from './helper.service';
...
providers: [ HelperService ]
...

Y listo, ya tenemos nuestro servicio que nos ayudará a comunicar nuestros componentes.

Ahora, vamos a crear dos componentes llamados: first.component.ts y second.component.ts . Dentro de first vamos a incluir el siguiente código:

import { Component, OnInit } from '@angular/core';
import { HelperService } from './helper.service';
@Component({
  selector: 'app-first',
  template: `
    <h1>Primer componente:</h1>
    {{ message }} <br />
    <input type="text" placeholder="Introduce un nombre"[(ngModel)]="editMessage">
    <button (click)="changeMessage()">Cambiar</button>
  `
})
export class FirstComponent implements OnInit {
message: string;
  editMessage: string;
constructor(private helper: HelperService) { }
ngOnInit() {
    this.helper.customMessage.subscribe(msg => this.message = msg);
  }
changeMessage() {
    this.helper.changeMessage(this.editMessage);
  }
}

¿Qué hace este componente?, bueno lo primero es importar el servicio del helper que previamente creamos.

Lo segundo es que el selector se llame app-first para poder incluirlo más adelante, lo siguiente es que pondremos una plantilla donde se incluye {{ message }} que es el mensaje que queremos cambiar a través de los componentes y ver que en ambos se replica.

Adicionalmente pondremos únicamente en el componente A (el primero por así decirlo) que podamos editar el mensaje y se vea reflejado en el componente B (o secundario).

Creamos las respectivas variables para llamar al mensaje original y suscribirnos a este mensaje cuando cambie. Como mencioné previamente, estamos observando los cambios en esta variable, es por ello que asignamos el suscriptor .

Reutilizando el ejemplo de las personas, como sabemos la persona A ya está siendo observada por la persona B, pero, ¿qué pasa si la persona C realiza una acción?, la persona B lo podrá ver, pero la persona A no lo sabrá, es por eso que suscribimos a la persona A a que también le avise la persona B si hay alguna acción en la persona C.

Posteriormente, generamos una función que ejecute la acción de cambio desde el Helper y así, entonces, se emita el evento. Es decir, cuando la persona A haga una acción la persona B reciba esa acción y se lo comente a la persona C, o si fue la persona C, se la comente a la persona A.

Ahora, vamos al componente secundario, en este pondremos casi el mismo código:

import { Component, OnInit } from '@angular/core';
import { HelperService } from './helper.service';
@Component({
  selector: 'app-second',
  template: `
    <h1>Segundo componente:</h1>
    {{ message }}
  `
})
export class SecondComponent implements OnInit {
message: string;
  editMessage: string;
constructor(private helper: HelperService) {}
ngOnInit() {
    this.helper.customMessage.subscribe(msg => this.message = msg);
  }
}

En esta ocasión no pondremos el cambio ya que el segundo solo estará recibiendo información en este ejemplo, sin embargo, si duplican la función changeMessage y la traen a este componente y a su vez, incluyen el formulario que se anexó en el primer componente, veremos que de igual forma cambia en el primero si se hace el cambio en el segundo y visceversa.

Hasta aquí sabemos que en caso de ser nuevos o relativamente nuevos en Angular claro (ya que supongo para llegar aquí tienen una idea de Angular) solo hace falta importar algunas cosas en el app.module

En este caso los nuevos imports son:

...
import { FormsModule } from '@angular/forms';
import { FirstComponent } from './first.component';
import { SecondComponent } from './second.component';
...

Que básicamente es el módulo para formularios de Angular y nuestros componentes y los anexamos al @NgModule dentro de las declaraciones:

...
declarations: [
    AppComponent,
    FirstComponent,
    SecondComponent
  ],
...

Y por supuesto hay que incluir ambos componentes en el `app.component.html` como `<app-first></app-first><app-second></app-second>`.

Y listo. Así se ve nuestro resultado:

A partir de aquí ustedes pueden realizar más acciones con esta idea, como mencioné agregar productos a un carrito comunicando componentes, si en el componente A muestra algo como “Inicie sesión para ver X dato” y en el B es el formulario de login puedan cambiar una vez que se loguee ese texto por otro, o muchas más cosas.

Por último, les dejo el repositorio de este tutorial:

https://github.com/asfo/comunicar-componentes

Nos vemos en el próximo tutorial.

¿Cuál es tu reacción?
+1
0
+1
0
+1
0
+1
1
+1
0
Total
0
Shares
Publicación anterior

Creando un componente de breadcrumbs (migas de pan) en Angular

Siguiente Publicación

Usando concatMap, mergeMap y forkJoin en Angular para peticiones HTTP

Publicaciones Relacionadas