Come abbiamo potuto vedere dagli esempi illustrati fin qui, l'approccio Model Driven o Reactive per la gestione delle form ci consente di impostare un valore iniziale per i controlli e di valutare la loro validità per la sottomissione dei dati. Ma mentre con l'approccio Template Driven potevamo sfruttare ngModel
e il two-way binding per avere una sincronizzazione immediata tra il contenuto della form ed il modello dei dati, con le Reactive Form questo non accade.
In realtà possiamo avere un comportamento analogo a quanto visto per le Template Driven Form, anche se con un approccio diverso e sotto il controllo del nostro codice. Infatti le Reactive Form mettono a disposizione la proprietà valueChanges, che implementa il pattern Publisher-Subscriber e ci avvisa quando viene effettuata una qualsiasi modifica alla form o ad uno specifico controllo della form. Tale è responsabile della reattività delle nostre form, da cui ovviamente il nome di Reactive Form.
Vediamo con un esempio come possiamo far reagire la nostra applicazione alle modifiche effettuate dall'utente sulla form. Supponiamo di aver arricchito il nostro componente con una proprietà model
che rappresenta il modello dei dati, cioè un articolo:
import {FormBuilder, FormGroup, Validators} from '@angular/forms';
import { Articolo} from '../articolo';
...
export class ArticoloFormReactiveComponent {
myForm: FormGroup;
@Input() model: Articolo;
constructor(fb: FormBuilder) {
this.model = new Articolo();
this.myForm = fb.group({
txtTitolo: ["", [ Validators.required,
Validators.maxLength(30)]
],
txtAutore: ["", [ Validators.required,
Validators.maxLength(20)]
],
txtTesto: ["", [ Validators.required,
Validators.minLength(2000),
Validators.maxLength(5000)]
]
});
}
}
Il nostro obiettivo è fare in modo che ogni modifica alla form si rifletta immediatamente sul modello dei dati, cioè la proprietà model
deve contenere ad ogni istante il valore dei relativi controlli sulla form. Per far questo aggiungiamo all'interno del costruttore del nostro componente la sottoscrizione agli eventi di modifica della form come mostrato di seguito:
export class ArticoloFormReactiveComponent {
myForm: FormGroup;
@Input() model: Articolo;
constructor(fb: FormBuilder) {
this.model = new Articolo();
this.myForm = fb.group({
...
});
this.myForm.valueChanges.subscribe(value => {
this.model.titolo = value.txtTitolo;
this.model.autore = value.txtAutore;
this.model.testo = value.txtTesto;
});
}
}
Tramite il metodo subscribe() della proprietà valueChanges abbiamo registrato un gestore il cui compito è di mappare i valori correnti della form sulle corrispondenti proprietà del modello dei dati.
In questo caso abbiamo registrato un gestore delle modifiche dell'intera form. In alternativa possiamo intercettare le modifiche ai singoli controlli della form sfruttando la stessa proprietà associata a ciascun controllo della form. Ad esempio, il seguente codice definisce un gestore specifico per le modifiche al controllo txtTitolo
della form:
this.myForm.controls["txtTitolo"].valueChanges.subscribe(value => {
this.model.titolo = value;
});
In questo modo abbiamo la possibilità di effettuare elaborazioni puntuali ed eventualmente differenziate su ciascun controllo della form.