Primi passi con Angular

Sicuramente possiamo considerare Google uno dei pionieri per quanto riguarda lo sviluppo e la distribuzione di framework front-end open source. Angular, anche conosciuto come Angular2, non è altro che l'iterazione successiva al famoso AngularJS.

Angular fa perno su due altri prodotti molto validi, ovvero RxJS e TypeScript, per fornire la migliore esperienza di sviluppo possibile tramite le migliori tecnologie front-end presenti sulla piazza. Data la vastità del framework, in questo articolo ci limiteremo ad analizzare come gestire, a livello base, l'input dell'utente.

# Binding agli eventi di input dell'utente

Molti eventi del DOM sono scatenati dalle azioni dell'utente, come il click di un link, il click di un bottone, l'inserimento del testo e così via.
Angular ci mette a disposizione un meccanismo per collegarci e reagire a tali eventi.

Nel seguente esempio vediamo come è possibile eseguire il bind di un event handler, onClickMe, all'evento corrispondente al click di un bottone:

<button (click)="onClickMe()">Click me!</button>

Possiamo vedere che l'evento click target è stato circondato dalle parentesi tonde, mentre dopo il segno di uguale è presente un template statement all'interno delle virgolette, che non è altro che codice JavaScript che verrà eseguito in risposta all'evento.

Quando eseguiamo il binding è bene prestare attenzione al''esection contect del template statement. Gli identificatori che possono apparire in un template statement appartengono ad un preciso contesto, solitamente il componente Angular che controlla il template:

@Component({
  selector: 'app-click-me',
  template: `
    <button (click)="onClickMe()">Click me!</button>
    {{clickMessage}}`
})
export class ClickMeComponent {
  clickMessage = '';

  onClickMe() {
    this.clickMessage = 'You are my hero!';
  }
}

Quando l'utente clicca il bottone, Anguar invoca il metodo onClickMe del componente ClickMeComponent.

# Leggere l'user input dall'oggetto $event

Gli eventi del DOM sono sempre accompagnati da un payload, contenente varie informazioni che potrebbero essere utili al componente. Vediamo un esempio dove ci mettiamo in ascolto dell'evento keyup generato da un elemento <input> per ottenere informazioni sul testo inserito dall'utente di volta in volta:

@Component({
  template: `
  <input (keyup)="onKey($event)">
  <p>{{values}}</p>
`
})
export class ClickMeComponent {
  values = '';

  onKey(event: any) {
    this.values = event.target.value;
  }
}

Quando l'utente preme e rilascia un tasto, avviene l'evento keyup, e Angular provvede il corrispondente event object nella variabile $event che viene rimbalzata al metodo onKey. Ovviamente il valore contenuto nel box di input sarà disponibile all'interno di event.target.value. Questo valore viene ogni volta memorizzato nella variabile d'istanza value che è interpolata all'interno di un tag <p>, il quale sarà quindi di volta in volta aggiornato con il suo contenuto.

# Tipizzare $event

Nell'esempio sopra abbiamo per semplicità forzato il parametro formale al tipo any. Il problema è che perdiamo completamente le informazioni sul tipo in gioco, informazioni che aiutano a prevenire errori.
Ecco come tipizzare correttamente il codice:

export class ClickMeComponent {
  values = '';

  onKey(event: KeyboardEvent) {
    this.values = (event.target as HTMLInputElement).value;
  }
}

# Filtrare l'evento keyup

Ipotizziamo di essere interessati non alla pressione di un qualunque tasto, ma solo al tasto Enter. Al momento l'event handler viene invocato ad ogni keyup, ma possiamo condizionare l'azione da intraprendere controllando la proprietà keyCode dell'event object:

export class ClickMeComponent {
  values = '';

  onKey(event: KeyboardEvent) {
    if(event.keyCode === 13) {
        this.values = (event.target as HTMLInputElement).value;
    }
  }
}

Un'altra strada consiste nel mettersi in ascolto dello pseudo-evento keyup.enter. Angular invocherà l'event handler solo quando l'utente preme il taso Enter:

@Component({
  template: `
  <input (keyup.enter)="onKey($event)">
  <p>{{values}}</p>
`
})
export class ClickMeComponent {
  values = '';

  onKey(event: KeyboardEvent) {
    this.values = (event.target as HTMLInputElement).value;
  }
}

# Conclusione

Abbiamo quindi visto le primitive di base per reagire agli eventi scatenati dall'utente.

Queste tecniche sono utili per progetti di piccola scala, ma diventano rapidamente prolisse quando si ha a che fare con diversi input dell'utente. Il data binding bidirezionale è un modo più elegante e compatto per gestire questi casi e Angular ci mette a disposizione la direttiva NgModel per questo.