Uno degli usi classici di JavaScript è la validazione dei dati inseriti dall'utente in un form prima dell'invio al server o comunque prima della loro elaborazione. Verificare che un valore obbligatorio sia stato effettivamente fornito dall'utente e che il valore inserito in una casella di testo sia un numero, eventualmente compreso tra i valori ammessi, o che la lunghezza di una stringa non superi una dimensione massima prefissata consente di evitare errori talvolta critici in fase di elaborazione dei dati.
L'introduzione di constraint validation API in HTML5 ha notevolmente semplificato il compito di JavaScript rendendo in diversi casi quasi non necessario il ricorso ad uno script per validare i dati.
In sintesi, i constraint validation
consentono di impostare dei vincoli sulla validità dei dati con un approccio dichiarativo, sfruttando una serie di attributi come ad esempio required
, per indicare che l'inserimento di un valore è obbligatorio, o min
e max
, per indicare il valore minimo e massimo che possono essere inseriti in un controllo. Il seguente è un esempio di casella di testo che richiede l'inserimento obbligatorio di un valore:
<input type="text" required />
Sarà compito dei browser analizzare tali vincoli in fase di invio e mostrare un messaggio all'utente nel caso in cui non vengano rispettati, come mostrato nella seguente figura:
Il messaggio e le modalità di visualizzazione dipendono dal browser. Tuttavia, utilizzando JavaScript, abbiamo la possibilità di intervenire sul meccanismo automatico di validazione e di estenderlo con criteri personalizzati.
Eventi legati ai controlli utente
Un primo aspetto che possiamo decidere è quando deve avvenire la validazione. Il comportamento predefinito del browser prevede che la validazione automatica dei dati venga effettuata in corrispondenza dell'invio al server, ma potremmo decidere di validare i dati quando l'utente passa da un controllo all'altro o quando il valore di un controllo cambia. Decidere quando validare i dati inseriti dall'utente corrisponde alla decisione di quale dei seguenti tre eventi gestire:
Evento | Descrizione |
---|---|
submit | l'evento di un form che si verifica quando si stanno per inviare i dati al server; per annullare l'invio dei dati nel caso in cui essi non siano validi è sufficiente che il gestore dell'evento restituisca il valore booleano false |
blur | questo evento si verifica quando un controllo perde il focus perchè l'utente si sta spostando verso un altro controllo |
change | evento di un controllo che indica che il suo valore è stato modificato |
Considerata la disponibilità di questi eventi, vediamo come possiamo intervenire per personalizzare la validazione predefinita.
Le constraint validation API aggiungono alcune proprietà sia ai form che ai controlli che ci consentono di verificare ed interagire con i vincoli di validazione. Ad esempio, la proprietà willValidate
ci consente di stabilire se un controllo è sottoposto ad un vincolo di validità o meno.
La proprietà ha un valore booleano che vale true
se per il controllo sono stati specificati uno o più attributi di validazione ed il controllo di validità su di esso non è stato inibito; la proprietà ha valore false
se il controllo di validità è stato inibito, ad esempio quando il controllo è disabilitato; ha infine valore undefined
quando non è stato specificato alcun attributo di validità.
Altra proprietà, sicuramente molto più utile della precedente, è validity
. Essa è un oggetto che ci consente di verificare se un controllo è valido e di risalire al vincolo eventualmente non rispettato. Consideriamo, ad esempio, il seguente codice:
var txtNome = document.forms.MyForm.txtNome;
txtNome.addEventListener("blur", function(e) {
var messaggio = "";
if (!e.target.validity.valid) {
if (e.target.validity.tooLong)
messaggio = "Superato il numero massimo di caratteri consentito! ";
if (e.target.validity.valueMissing)
messaggio = messaggio + "L'inserimento di un valore è obbligatorio! ";
e.target.setCustomValidity(messaggio);
}
});
L'oggetto Validity
Come possiamo vedere, abbiamo deciso di intervenire nella validazione predefinita del browser gestendo l'evento blur
. Abbiamo sfruttato la proprietà valid
dell'oggetto validity per stabilire se il controllo è valido. Nel caso in cui non sia valido, abbiamo verificato le proprietà tooLong
e valueMissing
per stabilire quale vincolo non è stato rispettato. Abbiamo quindi composto un messaggio relativo ai vincoli non rispettati e lo abbiamo impostato tramite setCustomValidity()
come messaggio da visualizzare al posto di quello predefinito dal browser. Il risultato che otterremo all'invio dei dati della form è il seguente:
Di seguito l'elenco delle proprietà dell'oggetto validity
, tutte di tipo booleano, che ci consentono di verificare i vincoli eventualmente imposti ad un controllo:
Proprietà | Descrizione |
---|---|
patternMismatch |
è true se il valore inserito dall'utente non rispetta l'espressione regolare indicata tramite l'attributo pattern |
rangeOverflow |
vale true se il valore del controllo supera quello specificato nell'attributo max |
rangeUnderflow |
è true se il valore del controllo è inferiore a quello specificato nell'attributo min |
stepMismatch |
è true se il valore del controllo non rispetta l'incremento stabilito dall'attributo step |
tooLong |
vale true se la lunghezza della stringa associata al controllo supera il valore previsto dall'attributo maxlength |
typeMismatch |
è true se il valore del controllo è di tipo diverso da quello previsto dall'attributo type |
valueMissing |
vale true se l'utente non ha inserito un valore come richiesto dall'attributo required |
Nell'esempio precedente abbiamo utilizzato il metodo setCustomValidity()
per personalizzare il messaggio d'errore predefinito del browser. Lo stesso metodo può essere utilizzato per impostare un proprio criterio di validazione, non basato quindi sui vincoli previsti dai constraint validation
.
Consideriamo ad esempio il caso in cui vogliamo consentire all'utente la modifica di una password e presentiamo su un form due campi password il cui valore deve coincidere per poter procedere con la modifica. Possiamo integrare il nostro criterio di validazione nel sistema di validazione predefinito gestendo, ad esempio, l'evento change
come mostrato di seguito:
var txtPassword1 = document.forms.MyForm.txtPassword1;
var txtPassword2 = document.forms.MyForm.txtPassword2;
var checkPassword = function() {
if (txtPassword1.value != txtPassword2.value) {
txtPassword1.setCustomValidity("Le password non corrispondono!");
} else {
txtPassword1.setCustomValidity("");
}
}
txtPassword1.addEventListener("change", checkPassword);
txtPassword2.addEventListener("change", checkPassword);
Questo è il classico caso di una "modifica password". Tramite setCustomValidity()
impostiamo un messaggio in caso di non validità oppure lasciamo la stringa vuota, ad indicare una validazione implicita, nel caso in cui i valori sono validi.
In aggiunta alla proprietà validity
, ciascun controllo e ciascun form prevede il metodo checkValidity()
il cui scopo è analogo a quello previsto dalla proprietà validity.valid
, ma con alcune caratteristiche interessanti.
Nel caso di un singolo controllo, esso verifica la sua validità e restituisce true
o false
se il controllo è valido o meno. Nel caso di form, invece, il metodo checkValidity()
verifica la validità di tutti i controlli contenuti in esso su cui sono impostati dei vincoli di validazione, restituendo true
se sono tutti validi, false
se almeno un controllo non è valido.
Sia per i form che per i singoli controlli, il metodo genera un evento invalid sul controllo non valido mettendo a disposizione quindi un'ulteriore modalità di personalizzare la validazione dei controlli.
In particolare l'accoppiata checkValidity() e invalid può risultare utile quando non intendiamo utilizzare un pulsante di tipo submit
per inviare i dati raccolti dal form, ad esempio nel caso di elaborazione dei dati sul client tramite JavaScript, o quando abbiamo disabilitato la validazione automatica del form tramite l'attributo novalidate
:
<form novalidate>
...
</form>