L’autocompletamento di un campo, una nuova ui di jQuery (2/2)
Nel precedente articolo abbiamo visto il principio di come implementare la funzione di autocompletamento messa a disposizione dalle user interface di jQuery.
L’abbiamo fatto tramite una lista predefinita di parole che abbiamo rappresentato tramite un array. Ora ci dedicheremo ad un caso più reale, ovvero quando questa lista di parole è contenuta in una tabella di un database.
Il lato client non cambierà di molto, mentre dovremo concentrarci particolarmente sul lato server allo sviluppo di uno script PHP per la gestione delle richieste.
Per fare questo, dovremo iniziare a chiarire il funzionamento di autocomplete.
Come inviare e ricevere i dati
La prima cosa che faremo sarà modificare il nostro script precedente in modo che come source non prenda più l’array parole (che possiamo anche cancellare a questo punto) ma il file source.php, in questo modo:
$(document).ready(function(){ $("#enter").autocomplete({ source: "source.php" }); });
Passando un file come source, il metodo autocomplete funzionerà in questo modo:
- Ad ogni rilascio di tasto (keyup), verrà letto il contenuto del campo.
- Il contenuto del campo verrà inserito nella variabile term ed inviato al file (nel nostro caso source.php) con il metodo GET tramite chiamata asincrona (AJAX).
- Il file php dovrà restituire un risultato nella forma di un array del quale ogni elemento è una notazione in formato JSON contenente i dati di una riga della lista di suggerimenti.
Vediamo subito cosa significa questo ultimo ed ingarbugliato punto.
Poniamo di avere nel database una lista di nomi, e che i nomi che iniziano con la “m” siano: Maurizio, Mauro e Marco.
Se scriviamo la lettera “m” nel campo, cosa deve succedere?
- Il file source.php dovrà intercettare la variabile term (che conterrà “m”)
- Bisognerà cercare nel database i campi il cui contenuto inizia con la lettera “m”
- Si dovrà infine creare l’array contenente i dati risultanti, in questa forma:
array({‘value’:’Maurizio’},{‘value’:’Marco’},{‘value’:’Mauro’});
Tramite questo formato, jQuery genererà la lista dei suggerimenti:
<li>Maurizio</li> <li>Marco</li> <li>Mauro</li>
Come è intuibile, con la chiave value, passiamo quello che dovrà essere il contenuto del tag <li>.
Ma potremmo decidere di far passare anche la chiave primaria del record (che potrebbe servirci in un secondo tempo) ed utilizzarla come id del tag. In questo caso, dovremo fare così:
array({‘value’:’Maurizio’,’id’:5},{ ‘value’: ‘Marco’,’id’:27},{‘value’:’Mauro’,’id’:75});
Il codice generato sarebbe questo:
<li id=”5”>Maurizio</li> <li id=”27”>Marco</li> <li id=”75”>Mauro</li>
Ma bando alle chiacchiere ed iniziamo a sviluppare la parte lato server.
Creare il database
Creiamo ora un semplice database nel quale potremo inserire dei nomi. Il database lo chiameremo autocomplete ed avrà un unica tabella chiamata nomi, della quale ti ho preparato la query; non hai che da eseguirla.
CREATE TABLE `nomi` ( `id` int(5) unsigned NOT NULL auto_increment, `nome` varchar(30) NOT NULL, PRIMARY KEY (`id`) ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=7 ; INSERT INTO `nomi` (`id`, `nome`) VALUES (2, 'Maurizio'), (3, 'Mauro'), (4, 'Marco'), (5, 'Luca'), (6, 'Luigi');
Creare il file con i parametri di connessione al database
Creiamo il file db_config.php nel quale definire le costanti contenenti di dati per la connessione al database:
define("HOST", "localhost"); define("USER", "root"); define("PASSWORD", "***********"); define("DB", "autocomplete");
Il file source.php
Creiamo ora un nuovo file e chiamiamolo source.php.
Come prima cosa includiamo il file di configurazione al database ed in seguito iniziamo a dichiarare la classe che chiameremo Autocomplete ed i membri term (nel quale inseriremo il valore passato dalla richiesta ajax) e conn (la risorsa di connessione al database).
include 'db_config.php'; class Autocomplete { public $term; public $conn;
Creiamo ora un metodo per la connessione al database:
private function dbConnect() { $this->conn = mysql_connect(HOST,USER,PASSWORD) OR die("Connessione non riuscita"); mysql_select_db(DB, $this->conn) OR die("Impossibile selezionare il database"); }
Scriviamo ora il costruttore di classe nel quale valorizzeremo la proprietà term ed invocheremo il metodo di connessione al database dbConnect()
public function __construct() { $this->dbConnect(); $this->term = mysql_real_escape_string($_GET['term']); }
Ed ora iniziamo a sviluppare il metodo printResult() che si occuperà di mandare in output il risultato nella forma che abbiamo visto precedentemente.
Come prima cosa costruiremo la query.
public function printResult() { $sql = "SELECT id,nome FROM nomi WHERE nome LIKE '$this->term%' ORDER BY nome ASC";
Selezioniamo id e nome dalla tabella nomi, quando nome inizia per il contenuto della variabile che ci è stato inviato.
Ora eseguiamo la query ed inizializziamo i due array che ci serviranno in seguito.
$res = mysql_query($sql, $this->conn); $return = array(); $arr = array();
Ora eseguiamo il ciclo in questo modo.
while($row = mysql_fetch_array($res)) { $arr['id'] = $row['id']; $arr['value'] = $row['nome']; array_push($return, $arr); }
Per ogni risultato trovato, creiamo un array associativo ($arr) con l’id ed il nome ed alla fine aggiungiamo questo array come nuovo valore dell’array $return.
In questo modo però il risultato avrà questa forma:
array(array(“id”=>5,”value”=>”Maurizio”), array(“id”=>27,”value”=>”Marco”) ....);
Ma nessun problema:
Alla fine non dovremo fare altro che passare $return per la funzione json_encode(); in questo modo il risultato sarà corretto e potremo mandarlo in output.
Nota: la funzione json_encode è disponibile dalla versione 5.2 di PHP; quindi se sul tuo hosting che monta PHP 4.3 (e che nonostante questo continui a pagare) non funziona, non è colpa mia.
Di seguito ti riporto il contenuto per intero del file source.php:
include 'db_config.php'; class Autocomplete { public $term; public $conn; public function __construct() { $this->dbConnect(); $this->term = mysql_real_escape_string($_GET['term']); } private function dbConnect() { $this->conn = mysql_connect(HOST,USER,PASSWORD) OR die("Connessione non riuscita"); mysql_select_db(DB, $this->conn) OR die("Impossibile selezionare il database"); } public function printResult() { $sql = "SELECT id,nome FROM nomi WHERE nome LIKE '$this->term%' ORDER BY nome ASC"; $res = mysql_query($sql, $this->conn); $return = array(); $arr = array(); while($row = mysql_fetch_array($res)) { $arr['id'] = $row['id']; $arr['value'] = $row['nome']; array_push($return, $arr); } echo json_encode($return); } } $autocomplete = new Autocomplete(); $autocomplete->printResult();
Conclusione
In questi articoli abbiamo analizzato un’importante novità del framework jQuery. Il metodo autocomplete ci permette di implementare una funzionalità complessa con uno sforzo minimo. Basti pensare che il solo fatto di passare il file che si occupa di gestire le richieste al parametro source comporta che jQuery si occuperà di gestire tutto il resto (leggere il contenuto del campo, inviarlo al file, intercettare la risposta, generare la lista dei suggerimenti, e come se non bastasse, mostrare una gif di caricamento nel campo intanto che aspetta i dati; insomma un grosso lavoro).
Sono molto convinto che ogni programmatore dovrebbe dedicare del tempo allo studio di framework e teconolgie affini in modo da razionalizzare e velocizzare i propri processi produttivi. Cosa ne pensi?
60 commenti
Trackback e pingback
-
Tweets that mention L’autocompletamento di un campo, una nuova ui di jQuery (2/2) | Your Inspiration Web -- Topsy.com
[...] This post was mentioned on Twitter by mtx_maurizio, Simone D'Amico. Simone D'Amico said: L’autocompletamento di un campo, una nuova… -
Come ordinare elementi con jQuery (1/2) | Your Inspiration Web
[...] il nuovo ordinamento e soprattutto a renderlo definitivo? Questo sarà l’argomento del prossimo articolo che risulterà inevitabilmente un po’…
Io dedico molto tempo alla formazione nel campo delle nuove tecnologie ( ultimamente sul framework jquery ).
Questo metodo che usa json_encode() però è da ricordate che funziona solo su stringhe utf-8.
Quando arriverà php 6 forse spereremo in utf-16 fino ad allora ci dobbiamo adattare all’ISO-8859-1.
Ciao rocco,
ci divertirmo insieme con php6 al ricovero per vecchi; magari ci scriveremo un articolo su your inspiration geriatrics :-)
hai perfettamente ragione, io speravo per il 2012 ma mi sa che non avremo questa fortuna se continua così
in verità credo tu abbia un errore … il termine da cercare non lo passi (anche se lo dici) … nun ce sta nessun GET[‘term’] … ma è una cagatella ;)
per il resto complimenti come sempre per la spiegazione passo passo, sempre ottimi articoli ;)
Se non dico una fesseria, non ci sta nessun $_GET[‘term’] perchè è proprio jQuery ad incertare di “default” un valore $_GET.
Penso, quindi, che anche mettendo un $_GET[‘variabile’] dovrebbe funzioanre lo stesso.
Questo perchè lo passa tramite $_GET. Se volessi un $_POST dovrei mettere nel javascript qualcosa tipo “$.post….”
Saluti.
Ciao Capo.
Non ho capito bene cosa vuoi dire.
jQuery passa la variabile term a source.php. Non ho capito cosa intendi :-)
@webby
no no. funziona solo con term.
Bene Maurizio grazie per l’articolo e per lo spunto di studio per l’autocompletamento.
Anche io cerco di dedicare del tempo allo studio dei framework.
E non é tempo perso, vero?
Hai per caso anche i riferimenti per un controllo simile, stile combo, sempre jquery?
Puoi essere più preciso Merlinox, non credo di aver capito.
Buona sera,
ho seguito attentamente questo tutorial (in realtà avevo già anticipato il lavoro) ma non mi funziona.
Ho incluso tutte le librerie necessarie e addirittura ricopiato direttamente il codice presente qui per vedere se funzionasse, ma niente da fare.
A parte che nel JS c’è una parentesi graffa in più (sotto a source), ma anche correggendo il problema non funziona.
Ho provato a raggiungere tramite browser il file “automplete.php?term=lu” e tutto funziona, ovvero il risultato mi viene restituito sotto forma di array.
Preciso che sono in locale.
Ciao webby.
Innanzitutto grazie per la segnalazione, in effetti c’era una graffa in più.
Per il resto, certo che se si usa mysql_real_escape_string prima della connessione al database… difficilmente funzionerà…. :-)
Ciao Maurizio,
ovviamente ho provato anche a togliere mysql_real_escape_string e lasciando solo $term = $_GET[‘term’] ma non funziona lo stesso.
Cioè quando immetto il testo non succede nulla.
Ho anche messo un LIMIT 30 nella query, per velocizzare il tutto ma non va,
Se posso, posso postare i due files, altrimenti apro una discussione nel forum.
Grazie.
Dunque, se immettendo i dati nella query string funziona, allora il problema é certamente nel codice jQuery o nelle inclusioni di librerie.
L’esempio del primo articolo ti funzionava?
Si Si, l’esempio del primo articolo funzionava e come.
Anzi l’ho ricopiato da quello che avevo già scritto nell’esempio della lettura da array.
Provo a postare tutto il codice nel forum allora, così i vari tag non mi vengono alterati.
Mi chiedevo se fosse possibile adattare l’autocomplete dell’articolo anche ad ASP.Net anzichè PHP! :-)
Si, ma in asp non ti posso aiutare :-)
Bell’articolo… lo stavo testando ma c’è qualche problemino da qualche parte. In pratica se c’è una vocale accentata, invece di mettermi il nome mi mette “null” nell’array.
Odio i problemi di codifica, sigh.
Mi auto-rispondo, basta piazzare un utf8_encode() codificando le variabili man mano che vengono ciclate :-)
Ma perché non utilizzi direttamente la codifica utf-8 per tutto. Documento, db, ecc…
P.S Te lo dice uno che detesta più di te i problemi di codifica, ma così facendo risolvi tutto. Tanto più che se utilizzi jQuery, ajax, ecc… li passa tutto per utf-8
Perché già lo faccio ma ogni tanto non basta e non riesco a capire come mai…
Nel caso specifico se non uso utf8_encode() non c’è verso di farlo funzionare, neanche impostando gli header in UTF-8:
Database, tabella, cella impostati utf-8?
Connessione al database impostata utf-8?
Salvataggio del documento impostato utf-8?
P.S i dati salvati nel database provengono da un documento con codifica utf-8?
DB, tabelle, campi e connessione UTF-8
Pagina creata in UTF-8
Pagina che ha generato i dati in UTF-8
Uhm nonostante mysql fosse convinto di usare una connessione UTF8 a quanto pare non era così… se uso
posso evitare di usare
utf8_encode()
Mi pare un po’ una boiata doverglielo dire ogni volta, quando di default dovrebbe già connettersi in UTF-8 :-S
Ma se io una volta scelto l’elemento della lista volessi inviare il modulo? Cioè vorrei simulare la pressione del pulsante Submit.
E se volessi passare alla query un altro parametro che mi ricavo in base alla pagina in cui mi trovo?
Quando trovo molti elementi mi ritrovo ad avere una lista infinita. Momentaneamente ho optato inserendo un “LIMIT” nella query, ma se volessi vederli tutti e magari mettere la lista ad una lunghezza fissa e poi con le scrollbar vedere anche gli altri?
beh, per la prima parte basta che utilizzi il gestore dell’evento change, passando alla funzione quello che vuoi fare.
per la seconda domanda direi che puoi aumentare il numero di caratteri a partire dai quali viene inizializzato l’autocompletamento.
Se anche questo non dovesse bastare, forse l’autocompletamento così come descritto non fa ala caso tuo.
E come faccio con l’evento change? Mi fai un esempio pratico per favore? Ancora non sono pratico con JQuery e mi aiuterebbe a capire ed imparare…
Grazie :)
Vorrei porre una domanda banale (credo).
Mi spiego, dalla pagina asincroma ricavo i campi ‘id’ e ‘ragione_sociale’. E fin qui tutto ok. Solo che nella pagina php vorrei inviare solo l’id e non la ragione sociale. So che i dati sono memorizzati correttamente nell’array return ma come faccio a selezionare solo ciò che mi serve?
Grazie
Nessuna risposta?
domandona, nella vecchia versione dell’autocompletamento c’era la possibilita di inviare le richieste al ready della pagina con il semplice parametro $(‘selettore’).search().
Questo potrebbe servire ad un’applicazione che prevede pagine di modifica come per esempio una scheda utente,facendo un searc() sul nome il plug in prevede a riempire gli altri campi ovviamente usando i dati provenienti dalla pagina richiamata in asincrono.
con il nuovo plug-in UI non riesco proprio a capire come si possa fare una cosa del genere. Qualcuno potrebbe darmi una mano?
oppure tale metodo potrebbe anche servire ad avviare il completamento dei campi al blur dell’input.
Nessuno che può aiutarmi?
Ciao junior.
Non sono certo di avere capito la domanda.
(Credo che con search() ti riferisci ad un plugin che comunque non conosco).
Quello che ho capito é:
una volta scelto il nome, vengono completati gli altri campi del form.
Questo lo puoi fare utilizzando il gestore dell’evento change. Devi recuperare gli altri dati ed inserirli nei campi.
provo a spiegarmi diversamente. la funzione search() si riferisce alla vecchia versione del plug in prima che diventasse UI.
allora, il problema di recuperare i campi e riempirli in seguito ad una selezione(selezione intesa come click sul menu che apparirà che se non sbaglio dovrebber essere .ui-menu-item) non sussiste.
il mio problema è proprio generare ad esempio l’evento change senza fare click sul menu. ad esempio, potrei trovarmi nella condizione in cui ho un value dell’input con autocompletamento non nullo ad apertura pagina e quindi vorrei che l’autocompletamento partisse in automatico per completarmi gli altri campi in base al valore dell’input suddetto senza far apparire menu a discesa e senza cliccare da nessuna parte.
spero di essere stato più chiaro ;-)
ciao junior,
puoi postare un link con un esempio di quello che vuoi fare?
http://www.cioccolateriatortoracelestino.it/aa/
potrai trovare qui un esempio.
nel campo 1 puoi digitare solo “hello” o “bye bye” e a seconda di quello che digiti si autocompleterà il secondo campo.
Ora il problema: come puoi vedere il campo uno ha un value di default = “bye bye” ora io vorrei che, una volta che il dom sia completo (“ready”) senza digitare nulla il secondo campo si autocompleti con il valore che scaturisce da “bye bye”, ovviamente immagina questa situazione in un form che ha 20 campi.
Il mio obbiettivo è autocompletare i campi senza settarli a mano da codice hatml ma che si autocompletino automaticamente a seconda del valore del campo uno
Con questo intendi dire con i dati corrispondenti al primo valore in ordine alfabetico?
Cioé, bye bye starebbe ad indicare questo?
no di default mi dovrei trovare in una situazione simile:
primo input = bye bye
secondo = ciao ciao
è come se dall’elenco dell’autocompletamento avessi scelto bye bye.
cacchio ma sono proprio infelice quando spiego le cose? ehehehehh
seeeeeee, semplice questo lo so, ma io voglio che lo debba fare l’autocompletamento, non devo farlo io a mano altrimenti nn avrebbe avuto senso aprire questa discussione nn ti pare?.va bhè cmq lasciamo stare risolvo io diversamente, troverò un modo per simulare la selezione.
grazie lo stesso.
Ciao, innanzitutto complimenti per lo script!
Volevo chiedervi un piccolo aiutino perchè lo script autocomplete non mi funziona. Usando firefox e firebug, mi danno questo errore:
TypeError: $(“#testinput”).autocomplete is not a function
Premetto che neanche la prima parte di questo script mi funziona.
Ho provato ad eliminare tutto, lasciando solo le chiamate js, lo script nell’header e il campo input text ma non va.
Dove sbaglio?
Se “$(“#testinput”).autocomplete is not a function” Vuole dire che la ui autocomplete non è stata caricata e quindi non la trova come funzione
Ciao hai risolto il problema con firefox? ho lo stesso messaggio
Gent.mo Maurizio
Sto realizzando una Web application per il Protocollo per l’azienda dove lavoro.
Premetto che sono un super novizio in fatto di programmazione e mi sto leggendo una marea di guide e tutorial per raggiungere la meta!
Uso EasyPHP per le prove in locale.
Per le tabelle MySql, php il linguaggio lato server e logicamente Html (4) e css .
Di questi linguaggi diciamo che riesco a capirne la logica e a realizzare cio’ che mi serve.
Veniamo al dunque:
ho un tabella DB chiamata anagrafica, dove i primi due campi sono id_anag e cognome ( in questo inserisco Cognome e nome) ed un Form con un campo mittente, dove grazie al suo tutorial, riesco ad avere l’autocompletamento con la chiamata asincrona con i dati del DB anagrafica.
In pratica nella lista generata dalla funzione jquery mi esce fuori ad esempio “PAOLINO PAPERINO” (Cognome e nome). il campo mittente serve a sapere se un utente è gia registrato o no. Nel senso che se non ho nessun nome corrispondente vuol dire che prima lo devo registrare.
Il problema si crea quando ho due nomi uguali. Infatti se nella tabella anagrafica fosse presente un Paolino paperino di roma ed uno di milano, come faccio a capire su quale cliccare??
La query php restituisce sia l’id che il mittente, ma la lista generata da jquery solo il campo nome (nel mio caso io ho inserito nome e cognome).
Insomma mi sono un po dilungato ma spero di essermi fatto capire.
nell’articolo parla dell’id che puo’ venire comodo in un secondo momento….ecco io sto al secondo momento…
Grazie e complimenti
Ciao Marco.
E’ chiaro che, se vi é la possibilirà di casi di omonimia, si dovrebbe estrarre dal database anche il campo città.
Ma la struttura del tuo database, ancor prima di questo, contiene una criticità;
Esso non é infatti in prima forma normale e questo può causare problemi nelle fasi successive.
Leggi questo articolo
https://www.yourinspirationweb.com/2010/10/26/la-strutturazione-dei-database-la-normalizzazione/
Ciao Maurizio e grazie della risposta .
Inizialmente il mio database era composto da id_anag – cognome – nome – via – comune – cap…etc etc
Per usare l’autocompletamento di questo articolo, non sapevo come fare a far comparire i dati completi, in quanto mi si popolava solo il cognome nel form.
sto leggendo come funziona il JSON e mi sono fatto un’idea su come possa fare per risolvere il problema.
Avrei bisogno che nel campo mittente del form (tramite la richiesta asincrona) venisse immesso il cognome, poi se ci sono più cognomi uguali, nel campo nome comparissero tutti i nomi associati a quel cognome, la VIA in un campo Via ed infine il Comune .Sarebbe una sorta di concatenamento dello script di autocompletamento.
Ho letto che con il json e ajax si possono passare da una pagina php tutti i dati che mi servono, ma non so costruire lo script che mi vada a popolare i campi del form html.
risolto così:
nel file source php cambiando la query e valorizzando l’array da passare con Json in questa maniera.
$arr[‘value’] = $row[‘ID_ANAG’] .” “. $row[‘COGNOME’] .” “. $row[‘VIA’] . ” ” . $row[‘N_CIVIC’] .” ” . $row[‘COMUNE’];
(come avro’ tempo rimettero’ un campo Cognome ed uno Nome nel Db :-) )
Scusami se non ho postato nel forum!
Complimenti per quello che fate!
Ciao Maurizio.
Vorrei chiederti come recuperare il valore dell’ id dopo aver selezionato il nome cercato.
Vorrei inviare l’ id selezionato ad un’altra pagina.
Anch’io sono arrivato allo stesso punto e con lo stesso problema di altri, come Marco P…….. premesso che sono esperto di php e invece novizio di jquery e digiuno completo di json.
Funziona tutto, ma anche se la pagina php restituisce id e value, non riesco assolutamente a capire come faccio a recuperare l’id nella pagina chiamante: ho un campo di tipo input che come value ha appunto il value che viene restituito, ma l’id?
Per riprendere l’esempio fatto nell’articolo, come faccio a recuperare (e quindi ad usare) i valori 5, 27, 75 … e non solo Maurizio, Marco, Mauro ?
grazie
E’ veramente un peccato che Maurizio non risponda più………. il sito è fatto benissimo e i consigli preziosi!
Però io ho ancora il problema di capite come fare a recuperare poi nella pagina client gli id che mi vengono restituiti da source.php ……….
Ciao Maurizio,
ho provato il tuo script e sono riuscito ad inserirlo nel mio sito, ma c’è una cosa che non mi funziona a dovere, cioè con i nomi che contengono apostrofi come D’Amico, D’Alessandro, ecc. Ti premetto che in tutte le altre procedure del sito funzionano bene. In un primo momento questi cognomi mi venivano visualizzati così: D'Amico, D'Alessandro alla pressione della lettera “d”. Ho applicato la funzione str_replace e vengono visualizzati correttamente. Però se al momento della ricerca io digito la lettera “d” seguita dall’apice non carica nessuno dei nomi che iniziano per “d” + apice come D’Amico, D’Alessandro.
Mi puoi aiutare a risolvere il problema, per favore?
Grazie in anticipo.
Tegatti
Dimenticavo.. i dati sono memorizzati all’interno di una tabella del databse.
Tegatti
Bello questo articolo complimenti. Ciao Sto implementando questa funzione di autocompletamento.
solo Una domanda ma per recuperare e quindi far comparire altri valori nel suggest ?
mi spiego. recupero per esempio codice prodotto e descrizione prodotto faccio l’encode json e tutto ok il valore value arriva e viene visualizzato in questo caso ho messo in value la descrizione del prodotto. ma io voglio che nel campo suggest che appare mi venga visualizzata anche l’altra chiave quella del codice prodotto, nel tuo esempio per intenderci è l’id. Ti sarò grato se mi darai un mano
Dopo aver passato la variabile $return per la funzione “json_encode();” come posso ricavarmi l’id nella pagina dove sto facendo la ricerca?
Ciao Maurizio, complimenti per l’articolo. Ho provato l’autocomplete e funziona,io prendo i dati da un database. Mi piacerebbe modificare l’aspetto grafico della tendina e la visualizzazione della lista. Hai qualche consiglio su come fare?grazie
Ciao Maurizio, volevo chiederti se conosci una possibile implementazione dello stesso risultato senza l’utilizzo di php.