giovedì 25 febbraio 2010

Validare campi form con asp e ajax (ajax form validator)

In questo post, voglio presentare un "form validator" che ho realizzato con il caro ASP classico, e l'aiuto di Ajax.

La finalità del sistema, è quello di ottenere una risposta immediata dal nostro server, sulla validità e formattazione o meno, dei dati inseriti nei campi della nostra form.

Alcuni esempi potrebbero essere: ottenere subito la risposta della validità o meno di un indirizzo email (si intende la validità del formato, non che poi la mail sia reale o no), oppure la ricerca nel nostro database della presenza o meno di un dato, ad esempio nella form di registrazione di un utente, controllare subito se la username inserita sia già presente....piuttosto che controllare la validità di formattazione di una data.

Ovviamente il sistema è poi aperto all'eventuale aggiunta di altri tipi di controlli, oltre a quelli che ho già inserito io.

Sostanzialmente lo script è costituito da:
- un file Javascript, che contiene il codice Ajax con la chiamata XmlHttpRequest
- un file ASP, che contiene tutti i tipi di controlli gestiti per ora, che restituirà il messaggio positivo o negativo dopo il controllo del dato passato
- ed infine la pagina che contiene la form, della quale vogliamo gestire i campi

Ora spiego il codice Ajax, e di seguito do un breve cenno su quello ASP, ma se volete scaricare direttamente l'esempio, andate a fondo post....

Codice Ajax usato:





var check;
var valore
var valore2

function check_valore(input, tipo_controllo, n, segno, tabella, campo, n1, n2, n3)
{

valore=document.getElementById(input).value;
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
check= new XMLHttpRequest();
check.onreadystatechange = function () {if (check.readyState == 4){ricevi_valore(input);}};
check.open("GET", "asp-validator.asp?tipo_controllo="+tipo_controllo+"&valore="+valore+"&n="+n+"&segno="+segno+"&tabella="+tabella+"&campo="+campo+"&n1="+n1+"&n2="+n2+"&n3="+n3, true);
check.send(null);
// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
check= new ActiveXObject("Microsoft.XMLHTTP");
if (check) {
check.onreadystatechange = function () {if (check.readyState == 4){ricevi_valore(input);}};
check.open("GET", "asp-validator.asp?tipo_controllo="+tipo_controllo+"&valore="+valore+"&n="+n+"&segno="+segno+"&tabella="+tabella+"&campo="+campo+"&n1="+n1+"&n2="+n2+"&n3="+n3, true);
check.send();
}
}
}

function check_valore2(input, tipo_controllo, n, segno, tabella, campo, n1, n2, n3, input2)
{

valore=document.getElementById(input).value;
valore2=document.getElementById(input2).value;
// branch for native XMLHttpRequest object
if (window.XMLHttpRequest) {
check= new XMLHttpRequest();
check.onreadystatechange = function () {if (check.readyState == 4){ricevi_valore(input);}};
check.open("GET", "asp-validator.asp?tipo_controllo="+tipo_controllo+"&valore="+valore+"&n="+n+"&segno="+segno+"&tabella="+tabella+"&campo="+campo+"&n1="+n1+"&n2="+n2+"&n3="+n3+"&valore2="+valore2, true);
check.send(null);
// branch for IE/Windows ActiveX version
} else if (window.ActiveXObject) {
check= new ActiveXObject("Microsoft.XMLHTTP");
if (check) {
check.onreadystatechange = function () {if (check.readyState == 4){ricevi_valore(input);}};
check.open("GET", "asp-validator.asp?tipo_controllo="+tipo_controllo+"&valore="+valore+"&n="+n+"&segno="+segno+"&tabella="+tabella+"&campo="+campo+"&n1="+n1+"&n2="+n2+"&n3="+n3+"&valore2="+valore2, true);
check.send();
}
}
}


function ricevi_valore(val) {
var risposta;
if (check.readyState == 2) {
risposta=check.responseText;

document.getElementById('re_'+val).innerHTML = '';
}
if (check.readyState == 4) {
risposta=check.responseText;

document.getElementById('re_'+val).innerHTML = risposta;
}
}



Partiamo dalla funzione principale, che si chiama "check_valore": tra paretesi vedete i parametri che posso passare alla funzione per poi eseguire i controlli nel file ASP.
I parametri che posso passare sono:

parametri obbligatori:
- input: contiene il nome del campo nel quale verrà inserito il valore da controllare
- tipo_controllo: qui dico che tipo di controllo voglio fare.
I valori possibili attualmente sono:
- testo: controlla che il valore sia una stringa
- numero_intero: controlla che il valore sia un numero intero
- numero_decimale: controlla che il valore sia un numero decimale con virgola o punto
- valuta: controlla che il valore sia un numero decimale con virgola o punto
- lunghezza: controlla la lunghezza del valore, e qui entrano in gioco due parametri opzionali, cioè "n" che conterrà il numero di caratteri da controllare in base al parametro "segno", che invece indicherà se il valore dovrà essere "minore o uguale", "maggiore o uguale" o "uguale" al numero impostato nel parametro "n"
- data: controlla che il valore sia una data
- email: che valida il formato dell'email inserita
- presenza_db_access_testo: controlla la presenza del valore in un database Access, e qui entrano in gioco altri due parametri che sono "tabella" che indica la tabella nella quale cercare, e "campo" che indica il campo nel quale cercare (il nome del database si inserisce nelle prime righe di configurazione del database, nel file ASP. Ovviamente nulla vieta di aggiungere anche un parametro per gestire anche il nome del database, nel caso ne avessimo più di uno)
- presenza_db_access_numero: cerca un valore numerico nel database
- presenza_db_mysql_testo: cerca un valore di testo in un database MySql
- presenza_db_mysql_numero: cerca un valore numerico in un database MySql
- sicurezza_password: infine in questo controllo, entrano in gioco i tre parametri "n1", "n2" e "n3", che servono a definire gli intervalli di numero di caratteri, per poi ricevere il livello di sicurezza del valore inserito
- sicurezza_password_img: come il controllo precedente, ma con una risposta di tipo visuale, come un'immagine(io ho messo un div con un colore di sfondo, ovviamente può essere sostituito con un'immagine diversa per le tre risposte "password poco sicura", "password abbastanza sicura" e "password molto sicura")
- controllo_uguaglianza_stringa: questo tipo di controllo, fa un confronto al volo di due valori in due diverse input. Quindi può servire in casi come l'inserimento di Password e reinserimento della Password per controllo, oppure per altri tipi di dati numerici, valute o date.


parametri opzionali:
- n: per indicare un numero di caratteri da controllare
- segno: indica il segno da utilizzare nel controllo del numero (valori possibili "<=", ">=", "=")
- tabella: indica la tabella del database nella quale cercare
- campo: indica il campo della tabella, nel quale cercare
- n1: indica l'intervallo per ottenere la prima risposta (es. password poco sicura)
- n2: indica l'intervallo per ottenere la seconda risposta (es. password abbastanza sicura)
- n3: indica l'intervallo per ottenere la terza risposta (es. password molto sicura)
- input2: invia un valore da una seconda input, da utilizzare per fare controlli al volo tra diverse input


Definiti i parametri della funzione, passiamo a vedere cosa fa la funzione: il corpo è la classica richiesta Ajax, con le due modalità in base al tipo di browser, che controlla se gestisce o meno l'ActiveX.

I parametri vengono inviati tramite URL, con metodo "Get" (si potrebbe fare anche la versione che invia i dati con metodo "Post"), e si ottiene la risposta dal server, che avrà eseguito i controlli richiamando il nostro file ASP, chiamato "asp-validator.asp".
La risposta verrà gestita nella seconda funzione, cioè "ricevi_valore": come vedete, anche questa funzione riceve un parametro, che non è altro che l'id del campo che stiamo controllando, e servirà per indicare l'id dell'elemento nel quale vogliamo inserire la risposta.
Io nell'esempio ho creato, a fianco della cella che contiene l'input, una seconda cella, che ha come id, un prefisso "re_" e poi lo stesso nome della input. A questo punto, posso indicare alla mia funzione Javascript, di inserire la risposta del controllo, nella cella che ha come id "re_" + "nome input da controllare".

Gli eventi gestiti per lanciare il controllo sono "onblur", che viene avviato quando si lascia la input, e "onkeyup", che viene avviato mentre si scrive, ogni volta che viene aggiunto un carattere(questo evento è usato nel controllo della sicurezza della password)

Fate attenzione a dare il giusto nome della form, nella funzione javascript. (io nell'esempio l'ho chiamata "form").

Qui potete testare l'esempio:



Qui potete scaricare lo zip con l'esempio: milanositi: Form Validator Asp Ajax

Ovviamente, se avete voglia di aggiungere qualche controllo fatelo...che magari poi aggiorniamo il file...se volete che ne aggiunga io....fatemelo sapere!

Se avete problemi nell'utilizzare il codice, fatemi sapere.

46 commenti:

  1. bell'articolo !!! mi serviva proprio anche se so che asp ormai è un po vecchiotto, purtroppo le mie app sono tutte in asp e sto cercando di implemetare ajax per la validazione dei campi di un form.

    Grazie =)

    RispondiElimina
  2. Questo commento è stato eliminato dall'autore.

    RispondiElimina
  3. ops riformulo : come si possono confrntare due campi dello stesso form con la funzione che tu descrivi ?

    bel post

    RispondiElimina
  4. Ciao e grazie a tutti per il tempo che avete dedicato a leggere i miei post...

    Ma tu che tipo di confronto vorresti fare? Fammi un esempio proprio nel dettaglio, così vedo anche come si può implementare un sistema che si possa riutilizzare.

    Diciamo che teoricamente, si potrebbe aggiungere la possibilità di inviare al validator, altri valori presenti negli altri campi...rimane solo da capire che tipi di confronti potresti volere... così proviamo ad impostarlo...

    RispondiElimina
  5. dunque una pratica molto diffusa è quella, ad esempio, di inserire la password e di reinserirla subito sotto, come accade anche per l'email.
    e dare subito l'avviso che i dati inseriti coincidono o sono errati.

    quindi confronto dei valori di uno stesso form.

    RispondiElimina
  6. Ok...non ci avevo pensato, ma effettivamente è una situazione molto frequente nelle form di registrazione.

    Allora: adesso ho aggiunto un'ulteriore possibilità di tipo di controllo, chiamato "controllo_uguaglianza_stringa"(con lo stesso concetto poi si potranno controllare numeri, valute, date...ecc...).
    In sostanza, allo script viene inviato anche il valore di una seconda input, e viene controllata l'uguaglianza tra le due stringhe. Come evento ho messo "onblur"...ovviamente si può cambiare con altri eventi, come magari "onkeyup" o quello che volete.

    Grazie per il tuo intervento...così abbiamo aggiunto un piccolo pezzo allo script..

    RispondiElimina
  7. bello bello ora lo testo =)

    Grazie Alessio

    RispondiElimina
  8. Riscaricalo che ho fatto un'ulteriore modifica...avevo dimenticato un valore...

    RispondiElimina
  9. ancora non riesco a farlo funzionare...ma grazie sei proprio un grande..Diana

    RispondiElimina
  10. Ciao Diana, se hai bisogno di una mano, fammi sapere...che ti aiuto volentieri...

    RispondiElimina
  11. prima aveva un errore, forse causato dall'ultima modifica non completa, il file JS è stato modificato ancora vedo....proviamo questo =)

    RispondiElimina
  12. ottimo ! FUNZIONA alla Grandissima ....mitico =)

    RispondiElimina
  13. Sì...mi ero dimenticato di una variabile nel Javascript...ora è ok.

    Grazie

    RispondiElimina
  14. Occhiiiooooo.....è saltato tutto il resto :D
    mannaggia a me, e a quando non sto zitto. sembra che funzioni solo la verifica di due campi, ma non esegue le altre verifiche contemporaneamente.

    Perdono è colpa mia :D

    RispondiElimina
  15. Hai ragione!...ho risistemato...poi modificherò ulteriormente i file...

    Ho diviso le due funzioni...poi appena ho tempo le unisco nella stessa funzione...

    Se non ci fossi almeno tu a seguire il blog...ed avvertirmi!

    Grazie e ciao.
    Lo zip è riaggiornato e anche lo script nel blog...

    RispondiElimina
  16. Ottimo lavoro, proprio stamattina facevo testa e muro perchè dovevo ricreare una cosa del genere,
    mi hai dato un ottimo spunto che implementerò come standard da qui a breve termine.

    Ciò che manca, secondo me è una funzione di controllo per codice fiscale e una per partita iva.

    Per la cronaca ho usato uno "span" con l'id "re_pippo" al posto della cella della tabella, mi garbava molto di più.

    RispondiElimina
  17. Ciao,

    sì ovviamente si possono aggiungere poi un sacco di "validazioni"...io ad esempio ho inserito uno script per la validazione dell'indirizzo mail..ma si possono appunto mettere validazioni di codici fiscali, partite iva..ecc.

    Buon lavoro allora!
    Ciao

    RispondiElimina
  18. Si ho inserito la validazione del codice fiscale e partita iva infatti.

    Avevo un'altra domanda: Come si puo far in modo di far uscire un risultato istantaneo dentro un 3 campo input.

    Esempio 3 campi input: input1, input2,input3.

    Se scrivo 11 nell'input1 e 13 nell'input2, far uscire il risultato (24) nell'input 3.

    Considera che con il tuo script ho fatto si che i valori dei form venissero passati a delle sessioni, ed i valori predefiniti dei campi sono proprio le sessioni. Mi sa refreeshare la pagina basterebbe. O come lo faresti tu ?

    RispondiElimina
  19. Ciao,

    allora, per fare l'operazione che dici tu, semplicemente metterei l'evento "onblur" nelle due input dove vanno inseriti i due valori, e mando i due valori nel file di verifica.
    Nel file di verifica compio l'operazione, e poi spedisco indietro il risultato e lo inserisco nella terza input.
    C'è solo da fare attenzione ad indicare, già quando parte lo script all'evento iniziale, in quale input dovrà andare a mettere il risultato... ma comunque non dovrebbe essere niente di complicato.

    Non ho capito quando dici che passi i valori nelle session... Che tu metta i valori predefiniti nelle session, può essere un discorso interessante...l'altro non l'ho invece capito.
    E comunque, il fine dell'usare Ajax dovrebbe essere quello di non dover fare "refresh" o "reload".

    Ciao
    Ale

    RispondiElimina
  20. Dimenticavo anche di dire che comunque è una cosa fattibile con Javascript direttamente...e forse molto più velocemente...

    RispondiElimina
  21. No no, per quel che riguarda il refresh, intendevo un refresh nel quadro(un td chiamato tot) che contiene il form , di modo da visualizzare i valori delle session aggiornati, perchè faccio compiere l'operazione proprio tra le session e il risultato è una nuova session. Quindi tu dici di utilizzare il js checkval2 che contiene i due campi di input iniziali. Mi viene un dubbio grosso come una casa, quindi significa che se ho un campo risultato che prende in considerazione diversi input dovrò passare tutti i valori di questi campi creando una funzione apposita.T_T

    RispondiElimina
  22. Così al volo ti direi di richiamare la stessa funzione da entrambe le caselle iniziali, e nella funzione mettere l'operazione che vuoi prelevando i due contenuti delle due input e poi facendo l'innerHTML nella terza casella... Penso sia la soluzione più veloce e comoda.

    RispondiElimina
  23. Ciao e complimenti per l'ottimo articolo, perfettamente funzionante :)
    A me non è chiaro come ottenere la risposta dal server utilizzando la funzione ricevi_valore;
    La validazione dei campi avverrebbe dopo un click su un button?
    GRAZIE! :)
    ciao

    RispondiElimina
  24. credo di non essermi spiegato bene :)
    vorrei poter inserire un button "registrami" cliccando il quale mi vengano subito validati i campi, se tutto è andato a buon fine i valori verranno inoltrati, diversamente vorrei poter visualizzare i messaggi d'errore accanto ai vari campi....
    ciauz

    RispondiElimina
  25. Ciao,

    il "bello" dell'Ajax è proprio di poter ricevere prima le risposte, perché viene fatta la chiamata asincrona prima ancora di aver inviato la form.
    Nel tuo caso, prima di cliccare sul bottone, puoi ricevere tutte le risposte, e volendo, mostrare il bottone solo quando tutte le risposte sono valide.

    Invece per fare come chiedi tu, devi usare semplicemente Javascript, e mettere sull'evento "onclick" del bottone(che farai come semplice bottone, non come "submit") tutte le validazioni, ma con Javascript, e alla fine della funzione che ha validato tutti i campi, metterai la funzione "submit" della form.
    Un po' più articolato...

    RispondiElimina
  26. infatti, subito dopo avert scritto il mio messaggio ho pensato ad una soluzione del tipo "attiva bottone se tutte le risposte sono valide" (le quali verranno inoltrate ad una seconda pagina)ma non sono riuscito ancora ad implementare :(
    Qualche consiglio sulla strada da seguire?

    RispondiElimina
  27. Dovresti ad esempio creare un array, che contiene due valori per stabilire se il controllo del campo è ok o no, mettendo magari valori tipo 0=non valido e 1=valido.
    Nelle varie funzioni che vengono richiamate quando l'utente inserisce i valori nei campi, fai il controllo e assegni il valore all'elemento corrispondente dell'array.
    Poi nella funzione finale, controlli se nell'array tutti gli elementi sono uguali a 1. Se sì, abiliti il tasto.

    Questa è una via...prova

    RispondiElimina
  28. è un'idea ma pensavo più semplicemente ad una variabile booleana che assume valore false per ogni validazione errata; quindi in base al valore della variabile attivo o disattivo il "button",ma non saprei come e in quale file far visualizzare l'input con "button"..

    RispondiElimina
  29. mmmmm....con una variabile semplice, devi stare attento che devi comunque fare prima il controllo su tutti i campi.
    Ad esempio, in una form di 5 campi, se passa già per il primo campo, fa la validazione, ed è tutto ok, la variabile assume il valore di "true" e quindi mostra il bottone? Devi comunque tenere traccia di 5 validazioni.
    Con un array, che inizialmente avrebbe 5 elementi a 0 , quindi "0,0,0,0,0"...ad ogni passaggio controlli il relativo elemento e lo valorizzi a 1, quindi se trova l'array "0,0,1,0,0" non visualizza niente...finchè non trova "1,1,1,1,1".
    Io vedo più complicato il sistema con una sola variabile. A meno che l'utente sia obbligato prima a passare su tutti i 5 campi, senza la possibilità di saltarli...boh.

    RispondiElimina
  30. si Alessio, hai perfettamente ragione, me ne sono accorto subito :( Solo però che non riesco proprio a capire come implementare il conrollo. Popolo l'array di 1 o ZERO a seconda degli esiti e poi? Dovrei controllare il valore "DISABLED" del button ma come?
    Pensavo ad un "if controlloarray = false then disabled" inserito nell'input button,ma non riesco a passare i valori. Negli altri casi si usa onblur, ok, ma qui?
    Ti sarei veramente grato se mi dessi un'idea...grazie

    RispondiElimina
  31. Effettivamente controllare le proprietà tipo "enabled", "selected" o "checked" delle input, non è semplicissimo...
    Conta che seguendo le direttive w3c, per mettere correttamente quelle proprietà, si dovrebbe mettere all'interno della input disabled="disabled", checked="checked" e selected="selected".

    Un modo per gestire quella proprietà può essere usare il "setAttribute".

    Ti metto un piccolo esempio, nel quale lancio la funzione "abilita" cliccando sul link "vai", che mi abilita il tasto, che inizialmente è disabilitato. Tu ovviamente modifichi la funzione, in modo che parta solo quando l'array è giusto, quindi con il tuo controllo if, che potrebbe anche semplicemente controllare che la stringa sia "1,1,1,1,1"



    <html>

    <head>
    <script type="text/javascript">
    function abilita(){
    document.getElementById('bottone').setAttribute('disabled', false);
    }
    </script>
    </head>

    <body>
    <a href="javascript: abilita();">Via</a>
    <form>
    <input id="bottone" type="submit" value="Bottone" disabled="disabled" />
    </form>
    </body>

    </html>

    RispondiElimina
  32. GRAZIE, ho verificato subito la funzione, pare che con FF il tasto non venga attivato, documentandomi ho trovato la seguenze soluzione:

    document.getElementById("bottone").removeAttribute("disabled");

    tutto il resto rimane uguale.
    Una cosa non mi torna ancora però, come attivare la function?
    Non vorrei utilizzare nessun link...con ONBLUR? ma non vale solo per i text type?
    Grazie per la tua pazienza e disponibilità

    RispondiElimina
  33. Ok, avevo provato solo IE.

    Per la funzione, io la attiverei con l'evento "onKeyUp", quindi quando l'utente sta scrivendo e "torna su il tasto"...
    Quindi, passando per i vari campi, controlli e valorizzi la variabile, e al campo finale (che può essere qualunque) il bottone si attiverà o meno.

    RispondiElimina
  34. faccio un pò il punto della situazione:
    1. nel file asp-validator popolo un array di 0\1 a seconda delle varie validazioni
    (il tasto si attiva se l'array contiene tutti 1)

    2. nel file form-validator inserisco la riga
    3. nel file ajax-validator dichiaro la seguente funzione

    abilita(){

    document.getElementById("bottone").removeAttribute("disabled");

    }

    la quale viene richiamata nella funzione check_valore subito dopo le due check.send

    ora però non capisco come poter passare il valore dell'array creato in modo da disabilitare o meno il buttom
    Credo che debba passare l'array alla funzione abilita(), ma come dal momento che il valore dei campi viene inviato dal file form...e l'array viene creato dal file asp-validator.asp?

    ...prima o poi ci riuscirò(emo) :)

    RispondiElimina
  35. al punto 2
    volevo dire che inserisco il campo input con onkeyup che richiama abilita()

    RispondiElimina
  36. Ciao Alessio

    ho provato a far validare una checkbox e l'operazione mi riesce a metà!

    Se spunto la checkbox il messaggio correttamente mi visualizza "OK!" ma se tolgo la spunta il msg rimane sempre su "OK!"

    RispondiElimina
  37. Il codice della checkbox è questo:
    <%
    opzione=request.form("PRIVACY")' Si/No - checkbox
    if opzione = 1 then
    spunta = " checked=""checked"""
    else
    spunta = ""
    end if
    %>

    RispondiElimina
  38. <input type="checkbox" name="PRIVACY" value="1"...

    RispondiElimina
  39. ..<%=spunta%> id="checkbox" onchange = "check_valore('checkbox', 'checkbox');" />

    RispondiElimina
  40. if request.querystring("tipo_controllo")="checkbox" then '-------CONTROLLO X CHECKBOX

    RispondiElimina
  41. if request.querystring("valore")= FALSE then

    RispondiElimina
  42. response.write"Campo vuoto!"
    else
    response.write "OK!"
    end if
    end if

    RispondiElimina
  43. scusa se ho scritto + post ma non riuscivo a scriverlo tutto insieme!

    RispondiElimina
  44. Sto cercando di modificare lo script non per eseguire una validita del valore nel campo, ma per poter estrarre da un db alcuni dati con filtro il valore passato. Quello che non riesco a capire penso sia nel file .js alla riga 60 circa document.getElementById('re_'+val).innerHTML = risposta;
    Se lascio questo impostato, si valorizza correttamente con il mio valore, ma io vorrei poter passare il mio valore non all'ID sopracitato, ma ad un campo imput già presente.
    Ho sotituito la stringa sopra citata con questa
    document.getElementById('PREZZO').innerHTML = risposta;
    document.getElementById('PREZZO').focus();
    ed aggiunto un focus che funziona, ma non il campo PREZZOH che resta vuoto.
    Dove sbaglio?
    Grazie
    Gianluca

    RispondiElimina
  45. Ciao,

    semplicemente devi usare "value" e non "innerHTML", se vuoi mettere il valore dentro alla input.

    quindi:

    document.getElementById('prezzo').value=risposta;

    L'innerHTML io lo usavo per iserire dell'html all'interno di un tag, come ad esempio un Div. Allora sì che userai innerHTML. Ma se devi modificare quella che è una proprietà interna di un tag, come appunto "value", devi usare in quel modo...se ad esempio volessi modificare la proprietà "src" di un'immagine, allora metteresti document.getElementById('prezzo').src= 'link all'immagine...';

    Ciao

    RispondiElimina
    Risposte
    1. Hai ragione,
      peccato che ho copiato la srtinga nel post senza cambiare il concetto. Nel codice ho messo

      document.getElementById('PREZZO').value= risposta;
      document.getElementById('PREZZO').focus();

      Comunque riprovo nuovamente per sicurezza

      Grazie
      Gianluca

      Elimina