Vediamo un esempio pratico di utilizzo della tecnologia Ajax in un form html. Supponiamo di voler creare un form che permette ad un utente di inserire, tra i vari dati, anche la sua regione e la sua città di residenza. Creiamo dunque due select box, una per la regione ed una per le città. Vogliamo usare Ajax per fare in modo che nel momento in cui l’utente seleziona la regione, nella select box delle città compaiano automaticamente solo le città della regione selezionata, senza fare alcun refresh della pagina. Il sistema è schematizzato in questa figura:

Premetto che ho costruito un piccolo database con 2 tabelle, una per le regioni ed una per le città. La pagina nella quale inseriremo il form si chiama citta.php. Ho utilizzato uno script php per poter caricare nella select Regione tutti i nomi delle regioni al caricamento della pagina. Nel momento in cui l’utente seleziona una regione dalla select box si attiva l’evento javascript onChange() che chiama la funzione getDati contenuta nel file javascript dove ho racchiuso tutte le funzioni usate in questo esempio. getDati comunica con getCitta.php che ci fornirà tutti i nomi delle città presenti nella regione scelta. Una volta ricevuti tutti i dati (formattati in XML) si richiama la funzione setCitta che provvede dapprima ad eliminare tutti gli elementi già presenti nella select Città per rimpiazzarli con i nuovi appena ottenuti.
Vediamo alcuni punti del codice. Ecco il codice del form contenuto in citta.php:
<form id="citta" name="citta">
Regione: <select name="regione" onChange="getDati('sel', document.citta.regione.value)">
<option value="" selected></option>
<?php
$conn = mysql_connect("localhost", "root", "");
mysql_select_db("citta", $conn);
$query = "SELECT * FROM regioni ORDER BY nome";
$res = mysql_query($query, $conn);
$linea = mysql_fetch_array($res, MYSQL_ASSOC);
while ($linea) {
echo '<option value="'.$linea['nome'].'">'.$linea['nome'].'</option>';
$linea = mysql_fetch_array($res, MYSQL_ASSOC);
}
mysql_close($conn);
?>
</select><br />
Città: <select name="sel" id="sel">
</select>
</form>Qui non faccio altro che impostare la chiamata alla funzione getDati nell’evento onChange e popolare la select delle regioni con i dati prelevati dal database. Il codice di getCitta.php è analogo, ma con piccole modifiche per inviare XML in modo corretto:
<?php header("content-type: text/xml"); echo '<?xml version="1.0" encoding="utf-8"?>'; echo '<citta>'; $conn = mysql_connect("localhost", "root", ""); mysql_select_db("citta", $conn); $query = 'SELECT nome FROM citta WHERE regione = \''.$_GET['regione'].'\'ORDER BY nome'; $res = mysql_query($query, $conn); $linea = mysql_fetch_array($res, MYSQL_ASSOC); while ($linea) { echo '<nome>'.$linea['nome'].'</nome>'; $linea = mysql_fetch_array($res, MYSQL_ASSOC); } mysql_close($conn); echo '</citta>'; ?>
La parte più interessante dell’esempio è ovviamente il file functions.js:
function getDati(eleTarg, regione) { if (serv) { var targ = document.getElementById(eleTarg); serv.open("GET", "getCitta.php?regione="+regione); serv.onreadystatechange = function() { if (serv.readyState == 4 && serv.status == 200) { setCitta(targ, serv.responseXML); } } serv.send(null); } } function setCitta(target, xmlDoc) { var opzione = document.createElement('option'); var num = xmlDoc.documentElement.childNodes.length; var elem = xmlDoc.documentElement; var i; deleteCitta(target); for (i = 0; i < num; i++) { var testo = elem.getElementsByTagName("nome")[i].childNodes[0].nodeValue; var opzione = new Option(testo, testo); target.options.add(opzione, -1); } } function deleteCitta(target) { var i; for (i=target.length-1; i>=0; i--) { target.remove(i); } }
Nella funzione getDati si nota subito che nella open si passa come parametro la regione scelta dall’utente allo script getCitta.php. In questo modo comunichiamo tramite il metodo GET con lo script. Essendo poi il risultato ottenuto un file XML, si nota l’uso di serv.responseXML che restituisce un oggetto XMLDocument. La parte che interagisce con XML si trova in setCitta. Innanzitutto otteniamo l’elemento radice del documento (in questo caso “citta”) tramite la funzione documentElement. Da questo otteniamo l’i-esimo nodo figlio “nome” con getElementsByTagName(<nometag>)[i] ed infine estraiamo il testo contenuto. Anche quest’ultimo è considerato nodo figlio del tag “nome”, quindi dobbiamo prima ottenere il nodo con childNodes[0] e poi possiamo prendere il testo contenuto attraverso nodeValue.
L’aggiunta e la modifica delle opzioni contenute nella select box avviene secondo questo metodo: si crea un oggetto di tipo Option passando come parametri il testo visualizzato ed il valore effettivo del tag option che verrà inserito. A questo punto, per inserire una nuova opzione nella select accediamo prima di tutto ad essa ed in particolare all’array dei suoi tag option tramite document.<nomeform>.<nomeselect>.options. Su questo chiamiano la funzione add che prende come parametro un oggetto Option e la posizione nella quale vogliamo inserire il nuovo tag (con -1 aggiunge alla fine). Per la rimozione di una opzione, si accede alla select e si invoca la funzione remove che prende come parametro l’indice dell’elemento da rimuovere: document.<nomeform>.<nomeselect>.remove(indice). In quest’ultimo caso occorre stare attenti a fare il ciclo al contrario poichè, dopo che si cancella un elemento, la loro numerazione cambia (l’elemento di indice 0 non è più quello di prima…). Perciò si cancella partendo da indici grandi ed arrivando fino allo zero.
Codice Sorgente
aprile 9th, 2009 at 14:34
gagliardo l’Ajax!! appena ho tempo provo a fare qualcosa…complimenti x l’articolo!!
aprile 9th, 2009 at 21:38
Ti ringrazio!
Eh si…è proprio una rivoluzione del web
novembre 23rd, 2009 at 17:10
L’unica cosa che non va e che non riesco a sistemare è che nella seconda select nei nomi delle città non compaiono le lettere accentate. Ad esempio la ì di Forlì non si visualizza. Come fare?
novembre 24th, 2009 at 11:59
OK, grazie lo stesso, ho scoperto l’arcano e ora è tutto ok.
febbraio 25th, 2010 at 20:34
Ciao e complimenti per l’articolo…ma io sono alle prime armi e non ho idea di come strutturare l’xml, qualcuno può farmi vedere un esempio completo?
Grazie
marzo 1st, 2010 at 23:23
Ciao Andrea, Grazie.
In realtà non c’è una regola precisa per strutturare l’xml, ma decidi tu la struttura di volta in volta in base al contesto
Cosa intendi con esempio completo?
giugno 10th, 2010 at 18:27
Ciao, ottimo articolo, sto provando a cambiare le citta e regione in Marca e Modello.
Ho solo un problema, devo attingere i dati da un db non mio, per cui non lo posso cambiare e i dati sono così organizzati:
NomeTabella
ID Marca Modello Prezzo
1 Casio dv56 230
2 ecc…..
una volta scelto marca e modello dovrebbe farmi visualizzare il prezzo
come devo modificare il tuo script per farlo funzionare con il db così?
Ciao e grazie
giugno 11th, 2010 at 12:38
Ciao Marco, grazie per il commento.
Innanzitutto devi modificare il file citta.php in modo tale da far comparire dentro la prima select le marche e non le regioni. Devi aggiungere inoltre un div con id=prezzo per far comparire il prezzo. Il file getCitta.php deve ridarti un file xml dove oltre al nome c’è anche il prezzo, quindi ad esempio il tag nome potrebbe diventare così: <modello prezzo=”230″>dv56</modello> oppure:
<modello>
<nome>dv56</nome>
<prezzo>230</prezzo>
</modello>
Supponendo di usare quest’ultima soluzione, nella funzione setCitta devi aggiungere questo dentro il ciclo for:
var testo2 = elem.getElementsByTagName(“prezzo”)[i].childNodes[0].nodeValue;
document.getElementById(“prezzo”).innerHTML = testo2;
Spero di essere stato chiaro, ciao!
settembre 3rd, 2010 at 14:29
ciao… utilissimo articolo… ti chiedo una cosa… io in mezzo tra regione e città ho anche la tabella provincia… cosa devo modificare per fargli fare lo stesso lavoro ma con l’aggiunta delle provincie… grazie…
settembre 3rd, 2010 at 14:41
un altra cosa importante… come è strutturato il tuo database???
settembre 3rd, 2010 at 17:22
Ciao Francesco, grazie per il tuo commento.
Per la provincia puoi guardare qualche commento dietro, dovrebbe essere il tuo stesso caso. Il database dell’esempio è strutturato in maniera molto semplice: c’è una tabella regioni ed una tabella città dove ogni record, oltre al nome della città contiene anche l’id della regione in cui si trova.
Ad ogni modo, il db può essere strutturato come vuoi
Ciao!
settembre 4th, 2010 at 15:31
grazie… io ho provato ad adattarlo alle mie esigenze ,a praticamente quando eseguo citta.php mi appare solo il form senza che il codice php venga eseguito. ho provato anche ad inserire degli echo in mezzo al php ma proprio non entra nel php. quale può essere il problema???