Paso de datos entre componentes

June 22, 2019 · View on GitHub

Input binding (del componente padre al hijo)

En esta sección vamos a ver cómo pasar datos de un componente a otro.

Partiendo del último ejemplo de crud básico, vamos a crear un componente que sea el encargado de presentar los detalles de cada usuario.

Esta era la capa que representaba al usuario en la template original (crud-basico.component.html):

  <div *ngIf="selectedUser" class="col-md-6">
    <h3>Detalle de {{selectedUser.name}}</h3>
    <div><label>Id: </label>{{selectedUser.id}}</div>
    <div>
      <label>Nombre: </label>
      <input [(ngModel)]="selectedUser.name" placeholder="name"/>
    </div>
  </div>

Creamos un nuevo componente:

ng g c child-comp

En child-comp.component.html nos llevamos es siguiente html:

    <h3>Detalle de {{selectedUser.name}}</h3>
    <div><label>Id: </label>{{selectedUser.id}}</div>
    <div>
      <label>Nombre: </label>
      <input [(ngModel)]="selectedUser.name" placeholder="name"/>
    </div>

En crud-basico.component.html cambiamos todo el html anterior por simplemente el selector de child-comp

  <app-child-comp *ngIf="selectedUser" class="col-md-3"></app-child-comp>

Para pasar el dato del usuario seleccionado al componente child-comp, ponemos lo siguiente:

  <app-child-comp *ngIf="selectedUser" class="col-md-3" [variable_para_child]="selectedUser"></app-child-comp>

Y en child-comp.component.ts informamos de que tenemos una variable de entrada con el decorador @Input

  @Input('variable_para_child')  user: User;

Y ya podemos probar el funcionamiento.

Output binding (del componente hijo al padre)

Vamos a ampliar child-comp con un botón para eliminar el registro

  <h3>Detalle de {{user.name}}</h3>
  <div><label>Id: </label>{{user.id}}</div>
  <div>
    <label>Nombre: </label>
    <input [(ngModel)]="user.name" placeholder="name"/>
  </div>
  <button class="btn btn-danger" (click)="delete()">Eliminar</button>
  delete() {
    //No tenemos acceso al listado completo para poder eliminar el elemento
  }

Pero nos encontramos que no tenemos acceso al listado completo de elemento. Vamos a informar al componente padre de que queremos eliminar el elemento, para que lo haga él. Esto se consigue gracias al decorador @Output que permite emitir eventos.

En child-comp.component.ts declaramos una propiedad decorada con @Output y cuyo valor es una instancia de EventEmitter.

  @Input('variable_para_child')  user: User;
  @Output() onChildDeleted = new EventEmitter<User>();

Cuando queramos lanzar el evento desde child-copm, llamaremos al método emit

  delete() {
    this.onChildDeleted.emit(this.user);
  }

Nota: El método next está obsoleto en favor de emit.

El componente padre puede bindear el evento:

  <app-child-comp *ngIf="selectedUser" class="col-md-3" [variable_para_child]="selectedUser" (onChildDeleted)="onDeleted($event)"></app-child-comp>

En $event recibirá lo que el child-comp haya metido como parámetro de entrada de la función emit

  onDeleted(user: User) {
    console.log('El child component quiere eliminar el item ' + user.id);
  }

Ejercicios

  • Separar en otro componente el listado de de usuarios.

  • Separar en otro componente el formulario de alta.

Índice