Form Submit in Ajax – Script per principianti

ajax-logoSolitamente evito turorial e articoli troppo tecnici visto che “saper spiegare” è una cosa più difficile di quanto sembri. Questo volta però ho realizzato uno scriptino che permetterà a chiunque (o quasi) di implementare l’invio di un form in Ajax senza bisogno di particolari abilità.

Premesse
Per chi non lo sapesse, Ajax è una tecnica di sviluppo web che tramite l’oggetto XMLHttpRequest permette l’invio e ricezione di dati senza bisogno di ricaricare la pagina con evidenti benifici in termini di velocità e usabilità del sito.

L’implementazione è più facile di quanto sembri anche per form già esistenti; è inoltre possile gestire anche l’eventualità che il browser abbia i javascript disabilitati redirigendolo in un’apposita pagina.

A differenza di molti script che si trovano in rete,ho cercato di parametrizzare i campi fondamentali così da poter specificare il messaggio di ‘Loading’ e l’ID del DIV in cui visualizzare la risposta del Form.

1. Lo Script
Innanzi tutto avrete bisogno di questo script che dovrete uploadare nel vostro sito e linkare nella sezione head della pagina del form in questo modo:

<script src="js/ajaxsbmt.js" type="text/javascript"></script>

Non dimenticate di modificare il percorso del JS con quello della cartella in cui l’avete uploadato.

2. Il Form
L’unica cosa da aggiungere rispetto ad un form classico, è il richiamo alla funzione xmlhttpPost associata all’evento onsubmit.
Il richiamo alla funzione xmlhttpPost va personalizzata secondo le vostre esigenze:

  1. Il primo paramentro (‘response_ajax.asp’) si riferisce alla pagina che riceverà i dati del form e risponderà
  2. Il secondo parametro (‘MyForm’) si riferisce al nome del form da cui prelevare i dati
  3. Il terzo parametro (‘MyResult’) si riferisce all’ID del DIV che conterrà la risposta del form ed il messaggio di attesa.
  4. Il quarto paramentro (‘Wait…’) si riferisce al messaggio di attesa che apparità durante l’invio dei dati. Potete anche inserire del codice HTML magari per far apparire un’immagine di caricamento.
<form name="MyForm" action="response_normal.asp" method="post" onsubmit="xmlhttpPost('response_ajax.asp', 'MyForm', 'MyResult', 'Wait...'); return false;">
<input type="text" name="sample_text" value="Test" />
<input type="submit" name="send_button" value="Send" />
</form>

La cosa interessante è che nel caso in cui il browser avesse il javascript disabilitati, i dati verranno inviati comunque alla pagina specificata nella proprietà action rendendo questo script di fatto accessibile.

4. Conclusioni
Visto quanto è facile realizzare un form “moderno”? Ho cercato di semplificare la questione il più possibile ma se avete dubbi, domande o problemi, lasciate un commento.
Lo script è stato testato con Firefox 2 e Internet Explorer 6 ma se avete la possibilità di testarlo con altri browser vi prego di comunicarmelo.

[dm]18[/dm]
QUI trovate una DEMO

NON DIMENTICATE DI VOTARMI SU DIGG ->

5. Immagini per il ‘Loading’
La fase di invio/attesa dati può essere personalizzata con una bella gif, eccovene alcune.
Ricordate che passando del codice HTML tramite la funzione xmlhttpPost i doppi apici (“) devono essere sostituti con lo slash e l’apice (\’).

Aggiungo in fine questo fantastico sito AjaxLoad che permette in perfetto stile web 2.0 di crearsi la propria immagine di caricamento.

136 Comments
  1. Io l’ho implementato facilmente già al primo utilizzo, ma avrei lo stesso una domandina: ho provato a farlo funzionare in un form in cui la pagina che processa i dati risiede in un altro dominio (cioè inserendo http://www.altrodomnio.it/risposta.php tra i parametri di xmlhttpPost) e, contrariamente al caso di pagina di risposta sullo stesso dominio, non funziona: mi carica la pagina di risposta invece di aggiornare il div.
    Sicuramente c’è una soluzione, ma volevo chiederti se riuscivi a darmi qualche dritta… : - ).
    Se riesco, la birra te la offro io 8 - )

  2. @Gionni: Sei un gran signore!
    @Luigi: I motivi possono essere molti, anche di incompatibilità con altri script presenti. Difatti non appena il javascript va in errore va in modalità “degradata” ed invia il form in modo normale.
    Più probabilmente, se ricordo bene, per motivi di sicurezza l’oggetto xmlHttpReq non permette interazione con domini diversi
    In questi casi uso FireBug per fare un debug e spulciare un pò tutto.
    Così alla cieca non saprei dirti di più!

  3. Ero al corrente degli stessi problemi…anche usando firebug ho notato che non c’era una soluzione immediata.
    Mi consola che sei arrivato alle mie stesse conlusioni ; - )
    Grazie comunque ancora per la risposta.
    Se mai avrò un blog, un link è tuo!

  4. Ritorno sull’argomento… nei miei esperimenti è sorta una curiosità. Mi spiego, se dopo l’invio, voglio che il form torni bello pulito (o per strafare, anche farlo sparire e al suo posto apparire la conferma dell’inserimento), che devo modificare?

  5. Potresti (come faccio io per il blog) pensare di gestire due diversi DIV: uno per la risposta ed uno per il form… ma credimi, si complica molto la cosa.
    E’ più facile includere anche il form nel DIV facendolo riapparire se necessario (in caso di errore) oppure scomparire in caso di invio corretto. A parole è facile, nei fatti dovrai lavorarci un pò…

  6. E’ quello che ho fatto io, con tanto di ricompletamento dei soli dati corretti.
    E’ stato un lavoraccio X - | (per me che programo da poco), ma alla fine funziona : - D.
    Io comunque non ho modificato NULLA dello script AJAX di Simone.
    Ho lavorato solo sulla pagina di risposta al form, nel mio caso in PHP.

  7. Ottimo Luigi!
    Mi fa piacere vedere che, anche con un minimo di conoscienze programmazione, si riesce ad adattare lo script alle diverse esigenze/linguaggi.

  8. Ciao Simone, complimenti per lo script: molto utile!
    Solo un dubbio: nel caso nel form avessi 2 pulsanti SUBMIT, ad esempio


    Vedo che anche cliccando su Conferma assume il valore di Cancella (o piu’ in generale l’ultimo valore “assumibile”).
    Ti risulta?!?
    Grazie mille!
    Ste

  9. Io lo uso con entrambi i pulsanti, il classico “invia” e “cancella” e funziona bene.
    Il pulsante “cancella”, però non è un submit, ma un tag input con type=”reset”, mentre “invia” è il classico input con type=”submit”.
    Tu usi un submit per cancellare i campi del form?

  10. Hai ragione Luigi, “non sono stato spiegato” : - )
    Ho un form con 4 pulsanti tutti submit:
    type=”submit” name=”action” value=”CONFERMA” – mi consente di modificare i dati di un record
    type=”submit” name=”action” value=”AGGIUNGI” – mi consente di aggiungere un record ex-novo nel db
    type=”submit” name=”action” value=”CANCELLA” – mi consente di eliminare il record
    name=”reset” value=”RESET” – mi resetta i valori del form
    Cliccando su AGGIUNGI, il pulsante “action” assume comunque valore “CANCELLA”

  11. Capito.
    Non sono così sgamato da dirti cosa non va nell’oggetto httprequest scritto da Simone (se davvero c’è qualcosa che non va…) o cosa dovresti fare per farlo funzionare come vuoi te.
    Probabilmente c’è da lavorarci sopra.

    Magari per capire meglio: quando dici “il pulsante “action” assume comunque valore “CANCELLA”” intendi che l’input submit assume sempre il valore cancella, giusto?

  12. Esatto! Assume sempre l’ultimo valore.
    Ovvero se avessi…
    type=”submit” name=”action” value=”CONFERMA” – mi consente di modificare i dati di un record
    type=”submit” name=”action” value=”AGGIUNGI” – mi consente di aggiungere un record ex-novo nel db
    type=”submit” name=”action” value=”CANCELLA” – mi consente di eliminare il record
    il valore di action e’ “CANCELLA” indipendentemente da quale “submit” schiaccio
    se avessi
    type=”submit” name=”action” value=”CANCELLA” – mi consente di eliminare il record
    type=”submit” name=”action” value=”CONFERMA” – mi consente di modificare i dati di un record
    type=”submit” name=”action” value=”AGGIUNGI” – mi consente di aggiungere un record ex-novo nel db
    il valore di action e’ “AGGIUNGI” (sempre indipendentemente da quale “submit” schiaccio).
    Ancora grazie mille!
    Ste

  13. Ho provato e ho risolto così e funge:
    – prepara una pagina di risposta diversa, per esempio “conferma.php”, “aggiungi.php” e “cancella.php”
    – nell’action del form, come valore passato all xmlhttpPost mettici una variabile a caso, chiamandola come vuoi, per sempio: target
    – nei 3 bottoni di submit modifichi l’attributo ‘onclick’ in questo modo: per CONFERMA metti onclick=”target=’conferma.php'”, per AGGIUNGI metti onclick=”target=’aggiungi.php'” e idem per CANCELLA.

    A quel punto la appena clicchi ti spara dentro la variabile target la pagina obiettivo per ogni diverso submit e ti produce il risultato desiderato.

    Un po’ maccheronica come soluzione, lo ammetto, in quanto ti costringe ad avere uno script diverso per ogni submit, ma finchè non ti viene in mente qualcosa di meglio…

    Col trucchetto dell’onclick sul submit potresti anche cambiare un valore del form che poi verrebbe passato in POST, ma queste prove le lascio a te…sono

  14. Luigi! Geniale!
    piu’ semplicemente
    <form name=’MyForm’ method=’POST’ action=’index.php’ onsubmit=”xmlhttpPost(‘index.php’,’MyForm’,’MyResult’,’Attendere prego…’); return false;”>
    Tanti campi, tanti valori, tanti blah… blah… blah…
    Quindi…
    input type=’hidden’ name=’action’ value=”
    input type=’submit’ name=’submit’ value=’Modifica’ onclick=”MyForm.action.value=’Modifica’”
    input type=’submit’ name=’submit’ value=’Elimina’ onclick=”MyForm.action.value=’Elimina’”
    input type=’submit’ name=’submit’ value=’Inserisci’ onclick=”MyForm.action.value=’Inserisci'”
    input type=’reset’ name=’reset’ value=’reset’
    quindi poi nella stessa pagina non controllo la variabile ‘$_POST[submit]’ (mi perdonerai ma io uso php) ma la variabile ‘$_POST[action]’
    Grazie per lo spunto! buon pomeriggio!
    Ste

  15. La tua è un’altra ottima soluzione.
    Lieto di esserti stato di aiuto 8 - )

    P.S. Ti perdono…anche io uso php : - D

  16. Piccolo consiglio: il valore di “action” viene usato di default per l’URL di destinazione del submit del form. Con javascript disattivato, un utente non potrebbe usare il tuo form.

    Se la cosa non ti preoccupa rimani pure così, altrimenti il mio consiglio è di cambiare il value di un altro campo hidden del form, per esempio ‘azione’ , quindi di controllare poi il valore di $_POST[‘azione’].
    Nell’action potresti risposta di default (che magari, se no ntrova settata la come si deve la $_POST[‘azione’] dice che per funzionare, il form ha bisogno di javascript attivato : - P ).

    E’ solo un suggerimento di usabilità, non di funzionamento, in quanto la tua soluzione così com’è è tranquillamente operativa.

  17. Precisazione giustissima!
    Grazie ancora!
    Ste

  18. Prego
    Mamma mia, come mi è sguillata la tastiera nell’ultimo commento X - |

  19. Sono in francia per qualche giorno, ma è stupendo vedere che vi aiutate da soli!
    Ciao ragazzi!!! : - D

  20. Ancora io!
    Magari e’ solo un mio problema su cui sto perdendo tempo inutilmente ma ho l’impressione che non funziona con un campo type=’file’ name=’immagine’
    Quando tento di caricare un’immagine (ovviamente ho gia’ verificato tutte le autorizzazioni sul server, grandezza max del file e tutti i blah blah blah…) non sembra funzionare.
    Mi aspettavo che php (sempre lui) mi valorizzasse la $_FILES invece nulla…
    Il tutto di contro funziona egregiamente senza ‘ajaxsbmt.js’ ma visto che c’e’… perche’ dovrei farne a meno?!?
    Buona notte!
    Stefano

  21. Qui non so come aiutarti.
    Nella mia breve esperienza di programmazione non ho mai avuto a che fare con il campo input=”file”, per cui non so come si comporta normalmente con i valori postati in ambito php.
    Tuttavia sono curioso: mi racconti come si comporta con e senza ajaxsbmt ?
    …chissà che mi venga in mente un altro suggerimento sgudiblo da darti ; - )

  22. Guarda, gli element file dovrebbero essere processati correttamente, però come ti consigliava Luigi ti conviene provare senza ajaxsbmt per vedere come si comporta.

  23. In realta’ la prova senza ajax e’ la prima che ho fatto e ovviamente funziona!
    Questa mattina mi son documentato meglio e sembra che quello dell’upload di file è un problema implicito di ajax in quanto è l’oggetto httprequest che non ne permette l’invio.
    se le cose stanno così l’unica soluzione rimane quella di nascondere la casellina type=’file’ all’interno di in iframe che e’ a sua volta contenuto nel frame principale: quando lancio l’upload in realta’ lo lancio solo x la pagina nell’iframe. Un po’ contorto ma credo possa funzionare. Quando ho completato il codice lo posto qui affinche’ ne facciate un buon uso.
    Buon pomeriggio!
    Stefano

  24. Tempo fa mi è passato sotto gli occhi un uploader di file in ajax (non ricordo dove).
    Il comportamento, ovviamente, era perfettamente asincrono come il nostro amato form.
    Puoi provare a cercarlo e implementarlo nel tuo form, oppure puoi darne una guardatina al codice per trovare la soluzione al problema.

  25. …ma ora che ricordo, era una soluzione che adottava un iframe. : - ?
    Mi sa che sei sulla strada giusta.

  26. Nel js, al posto di usare il formname, perchè non usi il formid?
    L’unica cosa che cambia (oltre ovviamente al nome del parametro formname), è la dichiarazione della variabile form all’interno della funzione getquerystring:
    function getquerystring(formid) {
    var form = document.getElementById(formid);
    Il vantaggio che ne trarresti sarebbe quello di avere un form validato per la DTD strict, visto che l’attributo name non è permesso per il tag form in quella DTD!
    Ciao

  27. Ottimo consiglio! Mi pare di ricordare che avessi avuto alcune problematiche, cmq provo e provvedo.
    Grazie

  28. Salve!
    Ho implemento il vostro script nel mio sistema… e mi sono accorto che non riconosce i caratteri accentati nelle risposte di errore! E’ possibile risolvere questo problema!?!

  29. Esattamente che intendi per “risposte di errore”?

  30. Ok! Risolto!

  31. Praticamente… io uso una piattaforma ASP…. e gl errori sui campi vengono controllato da un pagina ASP che scrive le risposte nel div di controllo del tuo script facendo un semplice response.write! I caratteri accentati venivano fuori con dei caratteri nn riconoscibili… allora ho forzato il setcode dei caratteri e ora va tutto bene!

  32. Si anche io faccio la stessa cosa ; - )

  33. Ma la pagina contenente il form viene ricaricata nel punto dove c’è il form o all’inizio? per capirci es questa pagina è molto lunga, se io invio il commento mi viene ricaricata la pagina qui dove c’è il form o in cima?

  34. Il bello è che proprio non viene ricaricato nulla. Semmai si riceve la riposta dalla pagina e viene visualizzata nel DIV con l’ID specificato nella chiamata del Form (Es. MyResult)
    In questa pagina, ho utilizzato una versione evoluta:
    1. Invio i dati
    2. Ricevo la risposta dal form (Es. Dati inviati correttamente)e la visualizzo quì sotto.
    3. Se tutto va bene faccio una chiamata (ricarico tutti i commenti) ad un’altra pagina e la visualizzo in un altro DIV ancora.

  35. ciao, e complimenti,
    ma ho una curiosità.Come mai nonostante processi in post lo script visualizza una querystring nella barra del browser?
    In questo caso mi passa in chiaro user e password.
    Volevo integrare ajax in uno script che uso di login.
    Attualmente io verifico le credenziali e poi eseguo un response redirect
    Con questo script ajax se ho notato che non mi esegue il redirect ma mi processa la pagina nella stessa.
    E’ giusto?
    Si puo fare un redirect ?
    Grazie
    Ciao

  36. Lo script, se non modifcato, esegue un post e non dovrebbe vedersi alcun paramentro di querystring.
    Per quanto riguarda il redirect non ci dovrebbero essere problemi ma non l’ho mai provato.

  37. Il redirect puoi farlo solo nella pagina che richiama lo script, e non nella pagina che elabora i dati.
    Per un redirect della pagina che ospita il form dovresti modificare qualcosina nello script di Simone.

  38. Ciao, ho usato il tuo script ajax in diverse occasioni e sempre con successo. Adesso il mio problema è che non riesco ad utilizzarlo all’interno di joomla.
    Ho importato correttamente lo script nell’header della pagina ed ho scritto il sorgente dell’articolo (contenuto di joomla) includendo gli attributi necessari nel tag

    . Tuttavia è come se lo script venisse ignorato… e la richiesta parte stampando la risposta (le righe di un db) in una nuova pagina invece che nel div di output da me impostato.
    Qualcuno ha suggerimenti in merito?
    grazie in anticipo
  39. Ciao, purtroppo il link al file non funziona più, non è che potresti rimediare?
    Grazie per la guida 😀

  40. Come non detto, ricliccando è uscito, boh!
    Grazie ancora 😀

  41. Sìsì, infatti riprovando subito dopo aver scritto il commento si è aperto, mentre la prima volta mi aveva reindirizzato alla home del blog

  42. ciao a tutti ho il seguente problema … il messaggio sia esso testo o immagine non mi viene visualizzato … lavorando in locale ho inserito nel file .php che processa il tutto la funzioncina sleep() settata a 5 secondi in modo tale che ci sia il tempo fisico per visualizzare il messaggio/immagine!
    Nulla mi viene restituito il valore del file .php ma nessun messaggio d’attesa

  43. Aggiungo solo che il problema si presenta su chrome e non ho idea del perchè lo faccia

  44. Cmq ti consiglio di provare anche con la funzione setTimeout, ma non sò se fa al caso tuo.
    Per poterti aiutare dovresti postare il codice.

  45. il codice è il seguente
    <form method="post" id="addcommento" action="inserisci_commento.php" onsubmit="xmlhttpPost('inserisci_commento.php', 'addcommento', 'risultatocommento', '’); return false;”>
    ….

    il problema credo sia di compatibilità e quindi da ricercare all’interno del file ajaxsbmt.js credo in questa porzione di codice

    if (self.xmlHttpReq.readyState == 4) {
    // Quando pronta, visualizzo la risposta del form
    updatepage(self.xmlHttpReq.responseText,responsediv);
    } else {
    // In attesa della risposta del form visualizzo il msg di attesa
    updatepage(responsemsg,responsediv);
    }

    ribadisco che il problema a me si presenta solo in chrome

  46. ho fatto alcuni test e la funzioncina
    updatepage(responsemsg,responsediv);
    se posizionata nell’if
    if (self.xmlHttpReq.readyState == 4)
    stampa il messaggio di attesa quindi deve esserci qualche problema con chrome nella gestione di quell’else !

    spero di essere stato chiaro 🙂

    domandina … all’interno della stessa pagina ho uno script che mi richiama una pagina php che carica tutti i commenti in un apposito DIV
    $(document).ready(function(){
    $(“#ultimicommenti”).load(“commenti.php”);
    });

    c’è un modo per far si che una volta inviato il form ed inserito il commento venga richiamata nuovamente la pagina commenti.php ?

  47. non riesco a scaricarlo…

  48. Ciao, ho usato il tuo script e lo trovo molto utile.
    Io lo uso per validare i dati inseriti dagli utenti e stampare il risultato a video.
    Problema: dopo la validazione però rimango nella pagina chiamata, mentre mi piacerebbe tornare (assieme al risultato stampato a video) sulla pagina chiamante.

    Come posso fare? Premetto che sono a digiuno di javascript/ajax

    Grazie mille in anticipo.

    • O non ho capito oppure qualcosa non funziona. L’utilità di questo form è proprio quella di inviare un form rimanendo nella pagina chiamante! lascia un link alla pagina che provo a vedere

  49. Purtroppo sto lavorando in locale, però posso postarti 2 righe di codice.
    Pagina sorgente:

    <form action="Valida.php" method="post" onsubmit="xmlhttpPost('Valida.php', 'validazione', 'MyResult', '’); return false;”>

    Valida.php:
    if(isset($_POST[‘via’])){
    $via = new Via($_POST[‘via’]);
    }

    La classe Via cerca a DB se la via è presente, se non lo è stampa un errore.
    Risultato esecuzione:
    il browser rimane in valida.php anche senza errori presenti.

  50. trovato l’arcano, non mi funziona con firefox

1 2 3

Rispondi a SimoneRodriguez Cancel reply