I menù a tendina sono un elemento di interfaccia veramente comodo: consentono infatti di elencare e raccogliere numerose opzioni di scelta o link in poco spazio, risolvendo spesso molti problemi di impaginazione e organizzazione del layout. Quando sono dinamici, poi, facilitano notevolmente anche la strutturazione dei contenuti.
Quando parliamo di menu a tendina dinamici intendiamo un set di almeno due di questi elementi in cui il secondo cambi contenuto in base alla selezione fatta nel primo, come nell'esempio che alleghiamo a questa lezione, in cui abbiam riadattato uno script disponbile sul sito Kaoswear.
Come si possono realizzare
Per realizzare questo tipo di menu abbiamo a disposizione tre vie:
- Usare JavaScript. È la via seguita nell'esempio di sopra. Basta sfruttare le potenti funzionalità degli array e passare i dati da un elemento all'altro. Il codice è tutto incorporato nella pagina e viene eseguito solo sul client.
- Usare codice ASP puro.
- Usare un approccio misto. Piuttosto difficile da implementare e ideale per siti complessi, combina la possibilità di connessione a fonti di dati offerte da ASP con JavaScript e array. Per farsi un'idea di questa soluzione consigliamo una visita a WebReference e all'esaustivo tutorial sull'argomento presente su quelle pagine.
Ognuna di queste soluzioni ha pro e contro. In questo articolo valuteremo in particolare la seconda, iniziando ad evidenziare i vantaggi che presenta rispetto all'approccio fondato solo su Javascript (1):
- facilità di realizzazione. Si tratta in sostanza di creare un database ben costruito e di impostare una semplice query SQL.
- pagine più leggere. Se le opzioni sono molte la soluzione basata sugli array può generare documenti pesanti, con un carico notevole sul client.
- facilità di gestione. Usare gli array non consente un'agevole aggiornamento delle opzioni, in quanto all'inserimento di un nuovo elemento bisogna modificare manualmente a cascata tutti gli altri. Estraendo invece i dati da un database il compito risulta semplicissimo.
Lo svantaggio di seguire la via basata solo su ASP è che su siti particolarmente affollati e con server non ben bilanciati si può riscontrare un calo delle performance proprio sul server. Lasciamo a voi la scelta e intanto iniziamo il nostro tutorial.
Al lavoro con Ultradev
Come accennato, nell'approccio ASP le opzioni degli elementi SELECT vengono estratti direttamente da un database e l'aggiornamento dinamico del secondo menu avviene semplicemente filtrando un recordset.
Partiamo quindi dal database. Nell'esempio che proponiamo abbiamo immaginato un primo menu con nomi di regioni italiane e un secondo con i nomi delle rispettive province. In Access è sufficiente creare due tabelle e collegarle nel pannello delle relazioni (figura 1):
Come si può osservare le tabelle sono semplicissime. La tabella "regioni" contiene due campi, un campo "id" come contatore e un altro, "regioni" con i nomi in formato testo. La seconda tabella presenta un campo "idprovincia" come contatore, un campo "idregione" fondamentale per la relazione con la prima tabella e un campo "provincia". La relazione, di tipo uno-a-molti, va fatta collegando "idregione" della tabella "regioni" con lo stesso campo della tabella "province".
Creato il database è necessario, come sempre in Ultradev, effettuare le consuete operazioni preliminari: definire il sito e le directory virtuali, stabilire un modello di applicazione (ASP) e un linguaggio di scripting (VbScript).
A questo punto si può creare un nuovo file (p. es. index.asp) e passare a definire una nuova connessione con il database. Usando il metodo ServerMapPath e supponendo di aver salvato il database in una cartella chiamata "dati" si può usare questa stringa:
"Driver={Microsoft Access Driver (*.mdb)};Dbq=" & Server.MapPath("/mio_sito/dati/nome_del_database.mdb")
Il secondo passo consiste nell'inserimento di un form al quale assegniamo il nome "form_reg" dal pannello Properties (CTRL+F3). All'interno del form inseriamo due menu a tendina (SELECT): nominiamo il primo "sel_reg" e il secondo "sel_prov".
Creazione dei recordset
Passiamo ora alla creazione dei due recordset da cui estrarre le opzioni per i menu. Partiamo dal recordset che restituirà i nomi delle regioni (rs_reg). Dalla finestra Data Bindings (CTRL+F10) clicchiamo su + e selezioniamo Recordset/Query. Osservando la finestra di configurazione (figura 2: clicca per visualizzare), a parte il nome e la connessione utilizzata notiamo che:
- abbiamo selezionato la tabella "regioni" e tutti i suoi campi (Columns/All)
- non abbiamo filtrato il recordset (vogliamo visualizzare tutti i nomi delle regioni!)
- abbiamo ordinato i record in base al campo "regione" in ordine ascendente
Il secondo recordset (rs_prov) è destinato ai nomi delle province. Ecco
la finestra di configurazione (figura 3: clicca per visualizzare).
Selezioniamo ovviamente la connessione utilizzata in precedenza, ma la tabella sarà "province" con tutti i suoi campi. La parte più importante è comunque l'ultima. Il recordset va infatti filtrato, per restituire solo i record che rispondono ai criteri che impostiamo. Nel nostro esempio esso dovrà restituire solo i nomi delle province che appartengono alla regione scelta nel primo menu a tendina. Dunque, nella prima casella selezioniamo il campo "idregione" (è quello che le due tabelle hanno in comune!); nella seconda usiamo l'operatore =; nella terza e nella quarta indichiamo che il valore viene passato dall'elemento "sel_reg" del nostro form. L'espressione SQL generata da Ultradev, visibile cliccando sul pulsante Advanced,
la seguente:
SELECT *
FROM province
WHERE idregione = MMColParam
ORDER BY provincia ASC[/code]
Dove MMColParam è una variabile così definita:
MMColParam = Request.Form("sel_reg")
Bene, ora abbiamo tutto il necessario per realizzare i nostri menu dinamici. È il momento di assegnare le opzioni e i valori ai SELECT.
Riempire i menù
Selezioniamo il menù "sel_reg", badando che sia visibile il pannello Properties (CTRL+F3). In questo caso noterete sulla destra il pulsante List Values: è da qui che si assegnano le opzioni ad un menu a tendina. Cliccando sul pulsante visualizzeremo questo box (figura 4):
È suddiviso in due sezioni. Item Label corrisponde al testo che verrà visualizzato nel menu (è il testo che in HTML è definito dal tag <option>). Value è il valore corrispondente ad una specifica opzione. Nel nostro caso Item Label e Value vanno estratti da un recordset. Quindi clicchiamo sul simbolo del fulmine per visualizzare un secondo box (figura 5):
Espandiamo il recordset "rs_reg", scegliamo il campo "regione" (quello con i nomi!) e diamo l'OK.
Allo stesso modo procediamo per assegnare il valore. Questa volta, però, sceglieremo il campo "idregione" dello stesso recordset.
Un ultimo ritocco. Nel box List Values potete notare in basso la casella "Select Value Equal To". Qui si imposta il testo che viene visualizzato quando si apre la pagina nel browser. Visto che l'aggiornamento dei menu avviene, come vedremo, aggiornando la pagina stessa, è importante settare questo parametro. Altrimenti si rischia di aggiornare il secondo menu, ma di vedere nel primo un valore non corripondente! In pratica, se l'ordine è "Lombardia - Lazio - Toscana - Sicilia", selezionando Lazio, visualizzo le province di questa regione, ma nel primo menu vedrò sempre al primo posto Lombardia! Spero di essere stato chiaro...Comunque, per impostare il valore, basta cliccare sul fulmine e scegliere dal recordset "rs_prov" il campo "idregione" (figura 6: clicca per visualizzare)
Il procedimento dovrebbe essere ora chiaro. Pertanto procedete ad assegnare opzioni e valori anche per il secondo menu (sel_prov). Questa volta setterere le opzioni in base al campo "provincia" e il valore in base al campo "idprovincia" del recordset "rs_prov".
Ultimo passo. Perchè tutto funzioni, dobbiamo inviare il modulo e processare la pagina, attivando gli eventi giusti.
Innanzitutto visualizziamo la finestra Properties e selezioniamo il form "form_reg". Nella casella Action digitiamo "index.asp" (ricordate? è il nome che abbiamo assegnato al nostro documento).
Ora attenzione, perchè dovremo intervenire direttamente sul codice. Selezionate con un click il menu "sel_reg", passate alla visualizzazione del codice (click sulla prima icona della barra degli strumenti). Aggiungete all'interno del tag SELECT questo codice:
onchange="this.form.submit()"
Il risultato sarà dunque:
<select name="sel_reg" onChange="this.form.submit()">
In questo modo la pagina verrà aggiornata automaticamente appena si cambia la selezione.
Salvate tutto. Aprite il vostro browser (mai fare la preview di pagine ASP con il tasto F12!) e...happy testing!
Una delle possibili applicazioni del sistema è quella di servire da input per filtrare un recordset, magari per una pagina di ricerca.
Torniamo all'esempio proposto nel tutorial. Operando sul primo select (sel_reg) si selezionava una regione e in base alla selezione venivano caricati nel secondo (sel_prov) i nomi delle rispettive province. A questo punto come potrebbe continuare l'applicazione? Si potrebbero visualizzare, ad esempio, tutti gli alberghi di quella provincia. Per fare ciò sarebbe necessario effettuare il submit del form per passare alla pagina dei risultati il valore di sel_prov come filtro del recordset. Ma, ricorderete, il submit del form viene già effettuato per caricare i nomi delle province! Se inserisco un pulsante submit al quale assegno come action il nome della pagina dei risultati, non funziona. Ecco la semplice soluzione.
Inserite nella sezione <head></head> della pagina queste poche righe di codice Javascript:
<script language="Javascript">
function vai(sel)
{
if (sel.selectedIndex == 0) return;
sel.form.action = "pagina_risultati.asp";
sel.form.submit();
}
</script>
Ovviamente dovrete sostituire pagina_risultati.asp con il nome della vostra pagina dei risultati. Nella quale, creando un recordset, lo filtrerete in base al valore del campo sel_prov. Ad esempio:
SELECT * FROM nome_tabella
WHERE nome_campo = Request.Form("sel_prov")
Ora, dopo i due select, inserite un pulsante di invio e richiamate la funzione dello script di sopra. Ecco il codice:
<input type="submit" name="Submit" value="Submit" onClick="vai(this)">
Fatto! Se volete che il submit avvenga con l'evento on_change del secondo select vi basterà eliminare il pulsante e aggiungere una piccola istruzione a sel_prov, così:
<select name="sel_prov" onChange="vai(this)">
Alla prossima!