Seguici su:

Angular Component e ChildComponent @Input() e @Output

Angular Component e Component Child @Input @Output

Angular Component e ChildComponent @Input() e @Output

Angular Passaggio di parametri tra Component e ChildComponent tramite @Input() con alias e @Output

Angular: vediamo un semplice esempio dell’uso di @Input per passare dei valori dal component principale al component figlio. Questo ci serve per costruire dei componenti riutilizzabili da altri componenti senza dover riscrivere il codice ogni volta. I dati scorreranno dall’alto verso il basso; quando creiamo un component che riceve i dati da un altro componet, dobbiamo dire esplicitamente ad Angular che i dati provengono dall’esterno utilizzando il decoratore @Input. Basterà posizionare il decoratore @Inputvicino alla variabile del componet figlio a cui si devono “iniettare” i dati che provengono dal componet esterno. Quando si usano dati provenienti da un component esterno, si deve usare un alias in modo da specificare un nome per la proprietà di input (es: @Input('alias'))

Vediamo subito un esempio utilizzando angular-cli per generare il progetto

ng new ex1-components --inline-template --inline-style

ng g interface IBook

ng g component Book --inline-template --inline-style --flat

Con questi tre comandi creiamo il progetto (ex1-components), creiamo l’interfaccia (IBook) e creiamo la classe (Book). Definiamo l’interfaccia IBook

export interface IBook {
    name: string;
    author: string;
    isbn: string;
}

Ora aggiungiamo al component figlio Book il decoratore @Input alla variabile theBook che conterrà ogni singolo elemento passato dal component padre che in questo caso è il nostro root component

import { Component, OnInit, Input } from '@angular/core';
import { IBook } from './ibook';

@Component({
  selector: 'app-book',
  template: `
    <p>
     {{theBook.name}} : {{theBook.author}} : {{theBook.isbn}}
    </p>
  `,
  styles: []
})
export class BookComponent implements OnInit {

  @Input('theBook') theBook: IBook;
  constructor() { }

  ngOnInit() {
  }

}

Nel component root usiamo il tag <app-book> iterando tramite la direttiva *ngFor sull’array dei libri e passando ogni singolo libro al component figlio (book.component) tramite il bind alla variabile theBook. Quindi ad ogni iterazione passiamo il valore presente in book dell’array books alla variabile theBook del componente figlio.

import { Component } from '@angular/core';
import { IBook } from './ibook';

@Component({
  selector: 'app-root',
  template: `
    <app-book *ngFor="let book of books" [theBook]="book"></app-book>
  `,
  styles: []
})
export class AppComponent {
  books: Array<IBook> = [
    { name: 'Angular', author: 'tutorial4dev', isbn: 'an6510984'},
    { name: 'Java', author: 'tutorial4dev', isbn: '0j761092'},
    { name: 'Javascript', author: 'tutorial4dev', isbn: '1js7622'}
  ];
}

Questo esempio è molto semplice proprio per far capire il passaggio di dati tra componete padre e componente figlio

@Output ed EventEmitter per generare eventi dal componente figlio al componente padre

Ora invece se vogliamo far comunicare il componete figlio con il componete padre dobbiamo fare uso degli eventi in modo da risalire verso l’alto, quindi emettere degli eventi dal basso (componente figlio) verso l’alto (componente padre) e gestirli al livello superiore. Per permettere al componente figlio di emettere un evento verso il componente padre dobbiamo:

  1. Importare la classe EventEmitter
  2. Definire un evento personalizzato che il componente figlio emetterà  utilizzando l’elemento events della direttiva @Component
  3. Creare una variabile istanza nella classe con EventEmitter()
  4. Chiamare il metodo emit per emettere l’evento

Creiamo una variabile istanza con il decoratore @Output() di tipo EventEmitter nel componente figlio in modo da emettere eventi quando richiesto, e modifichiamo il padre in modo da associare un attributo evento con lo stesso nome della variabile appena creata nel componente figlio. Angular emetterà un evento dal componete figlio al componente padre che invocherà l’istruzione alla destra dell’attributo, in questo caso, una funzione che chiama un alert

export interface IBook {
    name: string;
    author: string;
    isbn: string;
}
import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import { IBook } from './ibook';

@Component({
  selector: 'app-book',
  template: `
    <p>
     {{theBook.name}} : {{theBook.author}} : {{theBook.isbn}}
     <button (click)="delete(book)">Delete</button>
    </p>
  `,
  styles: []
})
export class BookComponent implements OnInit {

  @Input('theBook') theBook: IBook;
  @Output() bookDelete = new EventEmitter();
  
  constructor() { }
  ngOnInit() {}

  delete(book) {
    this.bookDelete.emit(book);
  }
}

Ora invece predisponiamo il componente padre per ricevere ed elaborare l’evento generato dal componente figlio.  Creiamo una funzione deleteBook() che lancerà un alert e scriverà all’interno il libro selezionato nel componente figlio. Poi settiamo nel template usando le parentesi tonde con il nome dell’evento del componente figlio e dall’altra parte il nome della funzione da chiamare che prende in input il nome del libro dalla lista dei libri.

import { Component } from '@angular/core';
import { IBook } from './ibook';

@Component({
  selector: 'app-root',
  template: `
    <app-book *ngFor="let book of books"
      [theBook]="book"
      (bookDelete)="deleteBook(book)">
    </app-book>
  `,
  styles: []
})
export class AppComponent {
  books: Array<IBook> = [
    { name: 'Angular', author: 'tutorial4dev', isbn: 'an6510984'},
    { name: 'Java', author: 'tutorial4dev', isbn: '0j761092'},
    { name: 'Javascript', author: 'tutorial4dev', isbn: '1js7622'}
  ];

  deleteBook(book: IBook) {
    alert('Deleting book:' + JSON.stringify(book));
  }
}

Quindi l’applicazione ha una lista di 3 libri, è in ascolto sull’evento bookDelete che quando si verifica attiva la funzione deleteBook() del padre. L’evento viene emesso dal figlio alla pressione del button Delete.

Qui il link all’esempio completo: tutorial4dev-angular/ex1-components

Pasquale Guarino

pasquale.guarino80@gmail.com