l'utente clicca sul pulsante di invio il valore degli elementi della form che hanno un attributo name viene inviato alla pagina del server /elaboraForm la cui risposta ci costringe a cambiare la pagina corrente.
In un'ottica più moderna che mantenga un approccio di tipo Single Page Application la soluzione precedente non è accettabile. Dopo aver raccolto e validato i dati di una form vediamo quali opzioni abbiamo con AngularJS per inviarli al server. Possiamo individuare tre metodi per l'invio dei dati al server.
Il primo approccio consiste nell'invio standard previsto dall'HTML specificando gli attributi action e method della form ed utilizzando un pulsante di tipo submit, come mostrato dal seguente codice:
<form name="myForm" action="/elaboraForm" method="post" novalidate>
<input type="text" ng-model="utente.nome"
name="nomeUtente" ng-maxlength="20"
ng-required="true">
<div ng-show="myForm.nomeUtente.$invalid">
Il nome utente è obbligatorio e non può superare i 20 caratteri
</div>
<button type="submit">Invia</button>
</form>
Questo approccio non coinvolge praticamente Angular: quando l'utente clicca sul pulsante di invio il valore degli elementi della form che hanno un attributo name
viene inviato alla pagina del server /elaboraForm
la cui risposta ci costringe a cambiare la pagina corrente.
In un'ottica più moderna che mantenga un approccio di tipo Single Page Application la soluzione precedente non è accettabile. Possiamo allora ricorrere alla direttiva ng-submit ed inviare i dati al server via Ajax sfruttando il servizio $http
. In questo caso definiremo la form nel seguente modo:
<form name="myForm" ng-submit="invia(utente)" novalidate>
<input type="text" ng-model="utente.nome"
name="nomeUtente" ng-maxlength="20"
ng-required="true">
<div ng-show="myForm.nomeUtente.$invalid">
Il nome utente è obbligatorio e non può superare i 20 caratteri
</div>
<button type="submit">Invia</button>
</form>
In questo caso abbiamo specificato l'invocazione della funzione di scope invia()
tramite la direttiva ng-submit
. Quando l'utente clicca sul pulsante di invio viene eseguita la funzione che si occupa di inoltrare i dati al server avendo la possibilità di effettuare eventuali pre-elaborazioni:
$scope.invia = function(utente) {
$http.post("/elaboraForm", utente)
.success(function() { alert("Dati correttamente inviati!");})
.error(function() { alert("Si è verificato un errore!");});
};
Un terzo approccio per l'invio dei dati di una form consiste nell'utilizzare un semplice pulsante con la direttiva ng-click, come mostrato di seguito:
<form name="myForm" novalidate>
<input type="text" ng-model="utente.nome"
name="nomeUtente" ng-maxlength="20"
ng-required="true">
<div ng-show="myForm.nomeUtente.$invalid">
Il nome utente è obbligatorio e non può superare i 20 caratteri
</div>
<button type="submit" ng-click="invia(utente)">Invia</button>
</form>
Questo approccio è sostanzialmente equivalente al precedente: invece di associare alla form il gestore di evento lo si associa al pulsante, ma l'effetto finale non cambia.
Prima di concludere questa sezione, segnaliamo alcuni accorgimenti da tenere in considerazione nella gestione delle form.
Per evitare che l'utente clicchi sul pulsante di invio prima della validazione dei dati è opportuno disabilitare il pulsante stesso fino a quando la form non è da considerare valida. Possiamo ottenere questo risultato combinando la direttiva ng-disabled con la proprietà $invalid della form:
<button type="submit" ng-disabled="myForm.$invalid"
ng-click="invia(utente)">Invia</button>
Verificare i dati durante l'inserimento
In determinate situazioni potremmo voler effettuare la validazione dei dati non man mano che l'utente li inserisce ma al momento dell'invio. Potremmo premettere nella funzione che invia i dati al server un blocco di codice che passi in rassegna i controlli della form verificandone la validità. In questo modo verremmo a perdere la semplicità dell'approccio dichiarativo che abbiamo visto finora.
La soluzione ideale che ci permette di mantenere l'infrastruttura di validazione che abbiamo esplorato in questa sezione è molto semplice: è sufficiente prevedere una variabile di scope che indichi se è stato richiesto di inviare i dati al server. Chiariamo l'idea con un esempio:
<form name="myForm" novalidate>
<input type="text" ng-model="utente.nome"
name="nomeUtente" ng-maxlength="20" ng-required="true">
<div ng-show="myForm.nomeUtente.$error.maxlength && myForm .prontaPerInvio">Il nome utente non può superare i 20 caratteri</div>
<div ng-show="myForm.nomeUtente.$error.required && myForm .prontaPerInvio">Il nome utente è obbligatorio</div>
<button type="submit" ng-click="invia(utente)">Invia</button>
</form>
Come possiamo vedere, abbiamo aggiunto alla condizione di visualizzazione dei messaggi d'errore il riferimento alla variabile booleana prontaPerInvio
che abbiamo associato alla form. Questa variabile viene inizializzata a false
all'interno del controller, impedendo quindi la visualizzazione dei messaggi d'errore, e viene impostata a true
dalla funzione di invio nel caso in cui la form non è valida, come mostrato dal seguente codice:
$scope.myForm.prontaPerInvio = false;
$scope.invia = function(utente) {
if ($scope.myForm.$valid) {
//invia dati al server
} else {
$scope.myForm.prontaPerInvio = true;
}
};
In questo modo manteniamo la semplicità dichiarativa dei vincoli di validazione sui controlli visualizzando le eventuali violazioni soltanto al momento dell'invio dei dati.