Cada uno de los elementos que componen la interfaz de una aplicación Angular se define como un componente, definidos en archivos html y ts.

[ezcol_1third][/ezcol_1third] [ezcol_2third_end]Tanto el componente padre como el componente hijo tienen su propio archivo ts (donde se define la lógica) y el archivo html (donde se define la parte gráfica). En el caso del archivo html del componente padre aparecerá la etiqueta asociada al componente hijo, de forma que existe una relación de pertenencia[/ezcol_2third_end].

<div class="container">
    <p>La comunicación en Angular se puede dar en dos sentidos:</p>

    <ul>
        <li>
            Cuando se quiere comunicar algo que está en el componente padre y se quiere pasar al componente hijo. Para este caso se utiliza el decorador @Input, al mismo tiempo que se declara como atributo del código html lo que se quiere comunicar
        </li>
        <li>
            Cuando se quiere comunicar algo que está en el componente hijo y se quiere pasar al componente padre. Para eso se utilza el decodaror @Output, generando un EventEmitter cuando se produce la comunicación, siendo recogida dicha comunicación en el elemento
            padre
        </li>
    </ul>

    <hr />

    <h1>Comunicación padre - hijo</h1>

    <div class="container-fluid top-space" style="background: #FFECB3">
        <h2>Elemento padre</h2>
        <p>
            Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento padre.component.html
        </p>
        <div>
            <input type="text" placeholder="Elemento a comunicar" #elemento />
            <button type="button" class="btn btn-primary" (click)="realizarComunicacion(elemento.value)">
        Realiza comunicación
      </button>
        </div>
        <div class="alert alert-danger top-space" role="alert" *ngIf="datoComunicar.length ==0 ">
            Estás intentando comunicar un dato vacío
        </div>
        <app-hijo></app-hijo>
        <br/>
    </div>
</div>

En el ejemplo se puede ver como se define en el html del padre todos los componentes que formarán parte de la interfaz gráfica, incluyendo la etiqueta <app-hijo> que muestra la parte gráfica asignada en el archivo html del componente hijo

<div class="container top-space" style="background: whitesmoke; padding: 5px">
    <h3>Elemento hijo</h3>
    <p>Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento hijo.component.html. El siguiente elemento está pasado desde el padre, gracias a la declaración @Input de la clase hijo.component.ts y la asignación
        desde el padre.component.html como atributo en el tag del componente. El elemento comunicado es:
    </p>
</div>

El resultado gráfico de todo el ejemplo a desarrollar es el siguiente:

La comunicación se puede dar en dos sentidos:

  • Un elemento que está en el componente padre se quiere pasar al elemento hijo que contiene
  • Un elemento que está en el componente hijo se quiere pasar al elemento padre donde está contenido

Comunicación padre – hijo

 

En este caso se quiere pasar una información desde el componente padre hasta el componente hijo, teniendo en cuenta que el segundo está contenido en el html del primero. Para ello los pasos a seguir son los siguientes:

  • Declarar un decorador @Input en el componente hijo. Este decorador servirá como el nexo de unión entre los dos componentes. Este decorador se asigna a una variable, la cual podrá ser utilizada en el html del componente hijo
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-hijo',
  templateUrl: './hijo.component.html',
  styleUrls: ['./hijo.component.css']
})
export class HijoComponent implements OnInit {

  @Input() componenteComunicar: string;

  constructor() { }

  ngOnInit() {
  }

}

El decorador componenteComunicar guardará el dato pasados desde el padre. Para utilizarlo en el html tan solo es necesario llamarlo con {{}} para utiliza su contenido

<div class="container top-space" style="background: whitesmoke; padding: 5px">
    <h3>Elemento hijo</h3>
    <p>Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento hijo.component.html. El siguiente elemento está pasado desde el padre, gracias a la declaración @Input de la clase hijo.component.ts y la asignación
        desde el padre.component.html como atributo en el tag del componente. El elemento comunicado es: <strong>{{componenteComunicar}}</strong>
    </p>
</div>
  • En el archivo html del padre que contiene la etiqueta del hijo, se utiliza la variable con decorador definida en el hijo como atributo de la etiqueta, utilizando data binding
<app-hijo [componenteComunicar]="datoComunicar"></app-hijo>

En este caso se trata de una variable definida en el archivo .ts del padre la cual recoge el contenido del input mediante la pulsación del botón

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

@Component({
  selector: 'app-padre',
  templateUrl: './padre.component.html',
  styleUrls: ['./padre.component.css']
})
export class PadreComponent implements OnInit {

  datoComunicar: string;

  constructor() { }

  ngOnInit() {
  }

  realizarComunicacion(dato: string) {
    this.datoComunicar = dato;
  }

}
<div class="container">
    <p>La comunicación en Angular se puede dar en dos sentidos:</p>

    <ul>
        <li>
            Cuando se quiere comunicar algo que está en el componente padre y se quiere pasar al componente hijo. Para este caso se utiliza el decorador @Input, al mismo tiempo que se declara como atributo del código html lo que se quiere comunicar
        </li>
        <li>
            Cuando se quiere comunicar algo que está en el componente hijo y se quiere pasar al componente padre. Para eso se utilza el decodaror @Output, generando un EventEmitter cuando se produce la comunicación, siendo recogida dicha comunicación en el elemento
            padre
        </li>
    </ul>

    <hr />

    <h1>Comunicación padre - hijo</h1>

    <div class="container-fluid top-space" style="background: #FFECB3">
        <h2>Elemento padre</h2>
        <p>
            Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento padre.component.html
        </p>
        <div>
            <input type="text" placeholder="Elemento a comunicar" #elemento />
            <button type="button" class="btn btn-primary" (click)="realizarComunicacion(elemento.value)">
        Realiza comunicación
      </button>
        </div>
        <div class="alert alert-danger top-space" role="alert" *ngIf="datoComunicar.length ==0 ">
            Estás intentando comunicar un dato vacío
        </div>
        <app-hijo [componenteComunicar]="datoComunicar"></app-hijo>
        <br/>
    </div>

    <h1 class="top-space">Comunicación hijo - padre</h1>
</div>

En evento click del botón ejecuta el método de la clase que iguala la variable datoComunicar al contenido del input, al mismo tiempo que la etiqueta <app-hijo> tiene como atributo el @Input declarado igualándolo a la variable

Comunicación hijo – padre

Se trata del mismo supuesto que el caso anterior, con la diferencia que el elemento que se quiere pasar entre componentes se encuentra en el hijo y el destino es el componente padre (que contiene al hijo en el html). Para poder hacer este tipo de comunicación se realizan los siguientes pasos:

  • Se declara un decorador @Output que es de tipo EventEmitter() en la clase ts del elemento origen
@Output() eventoComunicar = new EventEmitter();
  • Se crea un método que será llamado cuando se quiera realizar la comunicación. En este ejemplo al querer pasar un string entre componentes, dicho método recibe como parámetros el componente. Para poder asociar los datos a introducir en el EventEmitter se utiliza un par clave – valor, donde la clave se asocia a un dato concreto. En el ejemplo el dato que se quiere pasar se asociará a la clave elemento, la cual será utilizada cuando se quiera recuperar el dato
  realizarComunicacion(dato: string){
    this.eventoComunicar.emit({elemento: dato});
  }
  • El método creado es llamados en el momento en el que se quiere realizar la comunicación. En el ejemplo será llamado desde un botón situado en el elemento hijo
<div>
   <input type="text" placeholder="Elemento a comunicar" #elementoHijo />
   <button type="button" class="btn btn-primary" (click)="realizarComunicacion(elementoHijo.value)">
   Realiza comunicación
   </button>
</div>
  • En el archivo html del  elemento padre, dentro de la etiqueta asociada al elemento hijo se declara un evento con el mismo nombre del decorador @Output declarado en el punto uno, y se iguala a un método que se deberá crear en la clase asociada al componente padre. Este método recibe como parámetro un evento ($event) que es aquello emitido por el EventEmitter del hijo
<app-hijo-dos (eventoComunicar)="realizaComunicacionHijo($event)"></app-hijo-dos>
  • En el método creado en el punto anterior, se recuperarán todos los datos del evento emitido metiste los valores key asociados a cada uno de los datos
  realizaComunicacionHijo(event) {
    this.datoComunicarPadre = event.elemento;
  }

El código completo de los tres elementos utilizados es el siguiente:

<div class="container">
    <p>La comunicación en Angular se puede dar en dos sentidos:</p>

    <ul>
        <li>
            Cuando se quiere comunicar algo que está en el componente padre y se quiere pasar al componente hijo. Para este caso se utiliza el decorador @Input, al mismo tiempo que se declara como atributo del código html lo que se quiere comunicar
        </li>
        <li>
            Cuando se quiere comunicar algo que está en el componente hijo y se quiere pasar al componente padre. Para eso se utilza el decodaror @Output, generando un EventEmitter cuando se produce la comunicación, siendo recogida dicha comunicación en el elemento
            padre
        </li>
    </ul>

    <hr />

    <h1>Comunicación padre - hijo</h1>

    <div class="container-fluid top-space" style="background: #FFECB3">
        <h2>Elemento padre</h2>
        <p>
            Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento padre.component.html
        </p>
        <div>
            <input type="text" placeholder="Elemento a comunicar" #elemento />
            <button type="button" class="btn btn-primary" (click)="realizarComunicacion(elemento.value)">
        Realiza comunicación
      </button>
        </div>
        <div class="alert alert-danger top-space" role="alert" *ngIf="datoComunicar.length ==0 ">
            Estás intentando comunicar un dato vacío
        </div>
        <app-hijo [componenteComunicar]="datoComunicar"></app-hijo>
        <br/>
    </div>

    <h1 class="top-space">Comunicación hijo - padre</h1>

    <div class="container-fluid top-space" style="background: #FFECB3">
        <h2>Elemento padre</h2>
        <p>
            Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento padre.component.html. El elemento obtenido desde el hijo es: <strong>{{datoComunicarPadre}}</strong>
        </p>

        <app-hijo-dos (eventoComunicar)="realizaComunicacionHijo($event)"></app-hijo-dos>
        <br/>
    </div>
</div>
import { Component, OnInit } from '@angular/core';

@Component({
  selector: 'app-padre',
  templateUrl: './padre.component.html',
  styleUrls: ['./padre.component.css']
})
export class PadreComponent implements OnInit {

  datoComunicar: string;
  datoComunicarPadre: string;

  constructor() { }

  ngOnInit() {
  }

  realizarComunicacion(dato: string) {
    this.datoComunicar = dato;
  }

  realizaComunicacionHijo(event) {
    this.datoComunicarPadre = event.elemento;
  }

}
<div class="container top-space" style="background: whitesmoke; padding: 5px">
    <h3>Elemento hijo</h3>
    <p>Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento hijo.component.html. El siguiente elemento está pasado desde el padre, gracias a la declaración @Input de la clase hijo.component.ts y la asignación
        desde el padre.component.html como atributo en el tag del componente. El elemento comunicado es: <strong>{{componenteComunicar}}</strong>
    </p>
</div>
import { Component, OnInit, Input } from '@angular/core';

@Component({
  selector: 'app-hijo',
  templateUrl: './hijo.component.html',
  styleUrls: ['./hijo.component.css']
})
export class HijoComponent implements OnInit {

  @Input() componenteComunicar: string;

  constructor() { }

  ngOnInit() {
  }

}
<div class="container top-space" style="background: whitesmoke; padding: 5px">
    <h3>Elemento hijo</h3>
    <p>
        Todo lo que está contenido dentro de este div está declarado en el html correspondiente al elemento hijo.component.html. En este caso el siguiente elemento será comunicado gracias a un decorador @Output EventEmitter y recogido mediante un atributo en
        el elemento padre.
    </p>

    <div>
        <input type="text" placeholder="Elemento a comunicar" #elementoHijo />
        <button type="button" class="btn btn-primary" (click)="realizarComunicacion(elementoHijo.value)">
      Realiza comunicación
    </button>
    </div>

    <div class="alert alert-danger top-space" role="alert" *ngIf="elementoHijo.value == null ">
        Estás intentando comunicar un dato vacío
    </div>

</div>
import { Component, OnInit, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'app-hijo-dos',
  templateUrl: './hijo-dos.component.html',
  styleUrls: ['./hijo-dos.component.css']
})
export class HijoDosComponent implements OnInit {

@Output() eventoComunicar = new EventEmitter();

  constructor() { }

  ngOnInit() {
  }

  realizarComunicacion(dato: string){
    this.eventoComunicar.emit({elemento: dato});
  }

}